Use dimension when creating measure with Case statement in Looker - group-by

I am trying to create a measure conditionally based on a dimension.
My dimensions:
dimension_group: date {
hidden: yes
type: time
timeframes: [
raw,
date,
week,
month,
quarter,
year
]
convert_tz: no
datatype: date
sql: ${TABLE}.date ;;
}
dimension: status {
type: string
sql: CASE
WHEN UPPER(${TABLE}.status) ='APPROVED' THEN 'Approved'
WHEN UPPER(${TABLE}.status) ='PENDING' THEN 'Pending'
END;;
}
My Measures:
measure: xyz {
type: sum
value_format: "$#,##0.00"
sql: ${TABLE}.xyz ;;
}
measure: abc {
type: sum
value_format: "$#,##0.00"
sql: ${TABLE}.abc ;;
}
Measure with conditions:
measure: conditional {
type: number
value_format: "$#,##0.00"
sql: CASE WHEN ${status} = 'Pending' THEN ${xyz}
ELSE ${abc}
END;;
}
On my Explore, when I select date and conditional.  I keep getting the error:
ERROR: column "table.status" must appear in the GROUP BY clause or be used in an aggregate function
I understand what the error is. I am just not sure how to fix this. How do I resolve this error? I need all the dimensions and measures.

You can create a dimension conditional:
dimension: conditional {
type: number
value_format: "$#,##0.00"
sql: CASE WHEN ${status} = 'Pending' THEN ${xyz}
ELSE ${abc}
END;;
}
And then create a measure sum_conditional on that dimension:
measure: sum_conditional {
type: sum
value_format: "$#,##0.00"
sql: ${conditional};;
}

Related

Why function similarity return 1 while 2 value not the same?

Value in databbase: fullname="This is a pen."
My query: SELECT SIMILARITY(fullname,'This is a a pen') as sl from users
Result: sl=1
Why function similarity return 1 while 2 value not the same?
How can return 1 when value is the same. If value not the same return < 1?
The reason is that the period is stripped from the string when trigrams are created. Also, if a trigram occurs more than once (like from your ' a a ', these duplicates are ignored:
SELECT show_trgm('This is a a pen.');
show_trgm
═══════════════════════════════════════════════════════════════════════════
{" a"," i"," p"," t"," a "," is"," pe"," th","en ",his,"is ",pen,thi}
(1 row)
To test for equality, use the = operator. Perhaps something like this will satisfy:
ORDER BY fullname = 'This is a a pen' DESC,
similarity(fullname, 'This is a a pen') DESC

Filter data dynamically based on a hierarchical user id in cube.js

I have two tables called Writers and Publications where there is a foreign key publications.writer_id = writers.id
Writers
id (int)
parent_id (int)
role (varchar)
name (varchar)
path (ltree)
1
ADMIN
Firstname Lastname
2
1
EDITOR
Anon Anon
1.2
3
2
WEB EDITOR
Maisy Tickles
1.2.3
4
2
WEB EDITOR
Jack Beanstalk
1.2.4
5
3
WEB PROOFREADER
Sunny Ray
1.2.3.5
Publications
id (int)
writer_id (FK)
publication_name (varchar)
word_length (int)
published (datetime)
1
2
My First Magazine
6000
2019-09-09 09:00:00
2
2
My Second Magazine
6000
2019-09-16 09:00:00
3
3
My First Article
1000
2019-09-23 09:00:00
4
4
My First Article
1500
2019-09-23 09:00:00
5
4
My Second Article
600
2019-10-01 09:00:00
6
5
My First Piece
600
2020-10-01 09:00:00
I want to do a proof of concept in cube.js Developer Playground to show various charts. Is it possible to filter dynamically based on the user_id so that they can only access content that is equal to or in their subtree i.e.
If an ADMIN/EDITOR is using, they can see all the publications
If the WEB EDITOR (writers.id=4) is using the application, they can only see their own articles (publications.id in (4,5))
If the WEB EDITOR (writers.id=3) is using the application, they can see their publication and the WEB PROOFREADER's one (publications.id in (3,6))
The WEB PROOFREADER should only see their publication (publications.id=6)
These are the models I have set up so far
cube(`Writers`, {
sql: `SELECT * FROM public.writers`,
preAggregations: {},
joins: {
Publications:{
sql: `${CUBE}.id = ${Publication}.writer_id`,
relationship: `hasMany`
}
},
measures: {
count: {
type: `count`,
drillMembers: [id, name, created]
}
},
dimensions: {
id: {
sql: `id`,
type: `number`,
primaryKey: true
},
role: {
sql: `role`,
type: `string`,
},
};
cube(`Publications`, {
sql: `SELECT * FROM public.publications`,
preAggregations: {},
joins: {
Writer:{
sql: `${CUBE}.writer_id = ${Writers}.id`,
relationship: `hasOne`
}
},
measures: {
count: {
type: `count`,
drillMembers: [id, name, created]
}
},
dimensions: {
id: {
sql: `id`,
type: `number`,
primaryKey: true
},
wordLength: {
sql: `word_length`,
type: `number`,
},
};
I know there are filters and segments but these appear to be static. Is there any way to pass a writer_id to filter the relevant data dynamically? (I have no previous knowledge of JS)
I think these recipes can help you:
https://cube.dev/docs/recipes/role-based-access
https://cube.dev/docs/recipes/column-based-access
https://cube.dev/docs/recipes/passing-dynamic-parameters-in-a-query
I think you can query the cube from your front-end application with a filter of id.

Why is jsonb_path_query missing values for some rows?

I have this jsonb that I'm trying to flatten and migrate to conversations and tags tables:
{
id: '1',
type: 'conversation',
tags: [
{
id: '1',
type: 'tag',
name: 'foo'
}, {
id: '2',
type: 'tag',
name: 'bar'
},
{
id: '3',
type: 'tag',
name: 'baz'
}
]
}
But the following query is returning unexpected results:
SELECT
jsonb_path_query(payload, '$.id') #>> '{}' conversation_id,
jsonb_path_query(payload, '$.tags[*].name') tag_name
FROM conversations;
conversation_id | tag_name
1 foo
bar
baz
I want the following instead
conversation_id | tag_name
1 foo
1 bar
1 baz
I might be missing something obvious but I'm unclear:
Why conversation_id is NULL for the second and third row.
How I can get the results I want without parsing the jsonb in two passes.
This is how multiple set-returning functions in the select-list works since v10. See not starting "Before PostgreSQL 10, putting more than one set-returning function"
Your query can be converted to the simpler:
SELECT
payload #>> '{id}' conversation_id,
jsonb_path_query(payload, '$.tags[*].name') tag_name
FROM conversations;

How to count number of elements in the following JSON

I have a column in my Metabase table where the column entry is like the following:
{ “text_fields”: { “Weight”: “{:optional=>true, :priority=>4, :index=>false}” }, “checkbox_fields”: {}, “dropdown_fields”: { “Brand Name”: “{:optional=>false, :priority=>1, :index=>false, :options=>[“Non Branded”]}” }}
I want to get a net count of
text_fields
checkbox_fields
dropdown_fields
The desired answer, in this case, will be: 2 (1 text field + 0 checkbox field + 1 dropdown field)
Use jsonb_each to iterate over object keys/values, and jsonb_object_keys to extract the keys only.
Example (with sample data included):
SELECT * FROM mytable ;
mycolumn
---------------------------------------------------------------------------------------------
{"text_fields": {"Weight": 1}, "checkbox_fields": {}, "dropdown_fields": {"Brand Name": 1}}
(1 row)
SELECT *,
(SELECT sum((SELECT count(*) FROM jsonb_object_keys(v1)))
FROM jsonb_each(mycolumn) AS j1(k1,v1)
WHERE k1 IN ('text_fields', 'checkbox_fields', 'dropdown_fields')
) AS mytotal
FROM mytable;
mycolumn | mytotal
---------------------------------------------------------------------------------------------+---------
{"text_fields": {"Weight": 1}, "checkbox_fields": {}, "dropdown_fields": {"Brand Name": 1}} | 2
(1 row)

Postgres extract value from jsonb array

I have a jsonb field with an array like this one below:
[
{
"type":"discount",
"title":"Discount 10%"
},
{
"file":"zx5rP8EoacyfhqGndcSOnP8VYtkr9Ya8Nvf7oYL98YDsM1CLMYIurYvfVUU4AGkzBsovwssT0bq.pdf",
"type":"menu",
"title":"Some menu title etc"
}
]
I want to get the file attribute in case there is a type=menu in the array.
What I managed to do is to know if there is one, but how can I eventually extract the file value?
case when offers #> '[{"type":"menu"}]' then true else false end
I don't want to do something like this below because the array may not contain a discount type.
offers->1->'file'
Use jsob_array_elements() and ->> operator (see JSON Functions and Operators.)
with a_table(json_col) as (
values (
'[
{
"type":"discount",
"title":"Discount 10%"
},
{
"file":"zx5rP8EoacyfhqGndcSOnP8VYtkr9Ya8Nvf7oYL98YDsM1CLMYIurYvfVUU4AGkzBsovwssT0bq.pdf",
"type":"menu",
"title":"Some menu title etc"
}
]'::jsonb)
)
select value->>'file' as filename
from a_table,
lateral jsonb_array_elements(json_col)
where value->>'type' = 'menu'
filename
---------------------------------------------------------------------------------
zx5rP8EoacyfhqGndcSOnP8VYtkr9Ya8Nvf7oYL98YDsM1CLMYIurYvfVUU4AGkzBsovwssT0bq.pdf
(1 row)
Eg:
t=# with a as (with v as (select '[
{
"type":"discount",
"title":"Discount 10%"
},
{
"file":"zx5rP8EoacyfhqGndcSOnP8VYtkr9Ya8Nvf7oYL98YDsM1CLMYIurYvfVUU4AGkzBsovwssT0bq.pdf",
"type":"menu",
"title":"Some menu title etc"
}
]'::jsonb j)
select jsonb_array_elements(j) r from v) select r->>'file' from a where r->>'type' = 'menu';
?column?
---------------------------------------------------------------------------------
zx5rP8EoacyfhqGndcSOnP8VYtkr9Ya8Nvf7oYL98YDsM1CLMYIurYvfVUU4AGkzBsovwssT0bq.pdf
(1 row)