SQL Query like this below
select json_build_array(
json_build_object(
'entegrator_name', e2."name",
'provider_name', p."name",
'table1_count', count(t1.id)
)
)
FROM table1 AS t1
JOIN entegrators AS e2 ON e.entegrator_id = e2.id
JOIN providers AS p ON e.provider_id = p.id
GROUP BY e2."name", p."name"
result like this below
[{"entegrator_name": "entegrator_name", "provider_name": "provider_name", "table1_count": 6}]
[{"entegrator_name": "entegrator_name1", "provider_name": "provider_name1", "table1_count": 6}]
[{"entegrator_name": "entegrator_name2", "provider_name": "provider_name2", "table1_count": 6}]
...
But expected like this below, so in one row and one array.
[{"entegrator_name": "entegrator_name", "provider_name": "provider_name", "table1_count": 6},
{"entegrator_name": "entegrator_name1", "provider_name": "provider_name1", "table1_count": 6},
...]
how can I do this. Thanks :)
The issue with your query you need two aggregations:
COUNT to count your ids,
JSON_AGG to make a json array out of all json records
As long as aggregation functions cannot be nested, they can't be found within the same scope. Use a subquery to solve this problem.
WITH cte AS (
SELECT e2."name" AS e2_name,
p."name" AS p_name,
COUNT(t1.id) AS cnt_t1_id
FROM table1 AS e
JOIN entegrators AS e2 ON e.entegrator_id = e2.id
JOIN providers AS p ON e.provider_id = p.id
GROUP BY e2."name", p."name"
)
SELECT json_agg(
json_build_object(
'entegrator_name', e2_name,
'provider_name', p_name,
'table1_count', cnt_t1_id
)
)
FROM cte
You can use the JSON_AGG() aggregate function in the query like this:
SELECT JSON_AGG(
JSON_BUILD_OBJECT(
'entegrator_name', e2."name",
'provider_name', p."name",
'table1_count', COUNT(t1.id)
) ) FROM table1 AS t1 JOIN entegrators AS e2 ON e.entegrator_id = e2.id JOIN providers AS p ON e.provider_id = p.id GROUP BY e2."name", p."name"
Related
I am trying to filter rows from my Postgres database with below query. Everything works fine but when I try to check if latesttask column is null or has some value then it shows error:
error: column "latesttask" does not exist
SELECT *,
(
SELECT
JSON_BUILD_OBJECT(
'id', taskhistories.id, 'task', taskhistories.task,
'taskname', t.name, 'project', taskhistories.project,
'projectname', p.name, 'started_at',
taskhistories.started_at, 'stopped_at',
taskhistories.stopped_at
)
FROM
tasks AS t,
projects AS p,
latesttasks,
taskhistories
WHERE
taskhistories.user = users.id
AND latesttasks.task = t.id
AND latesttasks.project = p.id
AND taskhistories.id = latesttasks.taskhistory
AND (
LOWER(t.name) LIKE '%we%'
OR LOWER(p.name) LIKE '%we%'
)
) as latestttask
FROM
users
WHERE
(
latesttask IS NULL
AND (
LOWER(name) LIKE '%we%'
OR LOWER(email) LIKE '%we%'
)
OR latesttask IS NOT NULL
)
One "t" to many in your column alias latestttask.
But, more importantly, you cannot reference output column names in the WHERE clause anyway. There would have to be a column users.latesttask to make the WHERE clause work.
This would be a working equivalent with a LEFT JOIN to a LATERAL subquery:
SELECT *
FROM users u
LEFT JOIN LATERAL (
SELECT json_build_object(
'id', h.id, 'task', h.task,
'taskname', t.name, 'project', h.project,
'projectname', p.name, 'started_at', h.started_at,
'stopped_at', h.stopped_at) AS latesttask
FROM tasks t
JOIN latesttasks l ON l.task = t.id
JOIN projects p ON p.id = l.project
JOIN taskhistories h ON h.id = l.taskhistory
WHERE h.user = u.id
AND (lower(t.name) LIKE '%we%'
OR lower(p.name) LIKE '%we%')
) l ON true
WHERE l.latesttask IS NOT NULL
OR lower(u.name) LIKE '%we%'
OR lower(u.email) LIKE '%we%';
Please try with...
Select * from (SELECT
*,
(
SELECT
JSON_BUILD_OBJECT(
'id', taskhistories.id, 'task', taskhistories.task,
'taskname', t.name, 'project', taskhistories.project,
'projectname', p.name, 'started_at',
taskhistories.started_at, 'stopped_at',
taskhistories.stopped_at
)
FROM
tasks AS t,
projects AS p,
latesttasks,
taskhistories
WHERE
taskhistories.user = users.id
AND latesttasks.task = t.id
AND latesttasks.project = p.id
AND taskhistories.id = latesttasks.taskhistory
AND (
LOWER(t.name) LIKE '%we%'
OR LOWER(p.name) LIKE '%we%'
)
) as latesttask
FROM
users ) a
WHERE
(
latesttask IS NULL
AND (
LOWER(name) LIKE '%we%'
OR LOWER(email) LIKE '%we%'
)
OR latesttask IS NOT NULL
)
I have query like this:
SELECT user_input_id,
question_id,
type,
question,
COALESCE(value_text, value_free_text, value_date::text, value_number::text, value) AS all_value
FROM(
SELECT
a.id,
a.user_input_id,
d.id as question_id,
d.type,
d.matrix_subtype,
d.question,
a.value_suggested_row,
c.value as matrix_questions,
a.value_suggested,
b.value,
a.value_text,
a.value_free_text,
a.value_date,
a.value_number
FROM survey_user_input_line a
LEFT JOIN survey_label b on b.id = a.value_suggested
LEFT JOIN survey_label c on c.id = a.value_suggested_row
LEFT JOIN survey_question d on d.id = a.question_id
LEFT JOIN survey_user_input e on e.id = a.user_input_id
WHERE a.survey_id = 6
ORDER BY question_id, a.user_input_id, id, value_suggested_row) as TempTable
and this result:
I would like to grouping row where type is multiple_choice
and my wish result like this:
Can Anyone Help Me?
I would split your result into two part (with and without multiple_choice) and UNION them after grouping the multiple_choice part:
SELECT
*
FROM (--<your query>) s
WHERE type != 'multiple_choice'
UNION
SELECT
user_input_id,
question_id,
type,
question,
STRING_AGG(all_value, ',')
FROM (--<your query>) s
WHERE type = 'multiple_choice'
GROUP BY user_input_id, question_id, type, question
It could be more performant to put your subquery into a CTE:
WITH my_cte AS (
-- <your query>
)
SELECT
*
FROM my_cte
WHERE type != 'multiple_choice'
UNION
SELECT
user_input_id,
question_id,
type,
question,
STRING_AGG(all_value, ',')
FROM my_cte
WHERE type = 'multiple_choice'
GROUP BY user_input_id, question_id, type, question
I have a view for which I have created several subqueries, I'm trying to return one of the subqueries as json using -
row_to_json(err.*) as overall_totals
The subquery -
left join
(
SELECT q.id, SUM(q.total) AS total,
jsonb_agg(jsonb_build_object('count', q.total, 'type', q.name)) AS totals
FROM (
SELECT r.id AS id, e.name, COUNT(de.value_id) AS total
FROM table_c de
JOIN tests.error e
ON e.id = de.value_id
JOIN table_a p
ON de.process_id = p.id
Join table_b r on p.root = r.id
GROUP BY e.name, r.id ) q
GROUP BY q.id
) err on err.id = rs.id
This works fine and returns as json, however, I only want to return total and totals of the "err" sub-query and not q.id. I need the q.id in the sub-query so that I can join the query onto the rest of the view but I don't want it to be stored in overall_totals. How can I get around this? Is it possible to select certain values into row_to_json?
If you are fine with returning jsonb instead of json, then you can use the - operator:
to_jsonb(err.*) - 'id' as overall_totals
You can add more subquery, something like this
SELECT row_to_json(err2.*) as overall_totals
FROM
(
SELECT err.total, err.totals
FROM XXX_TABLE RS
left join
(
SELECT q.id, SUM(q.total) AS total, jsonb_agg(jsonb_build_object('count', q.total, 'type', q.name)) AS totals
FROM
(
SELECT r.id AS id, e.name, COUNT(de.value_id) AS total
FROM table_c de
JOIN tests.error e
ON e.id = de.value_id
JOIN table_a p
ON de.process_id = p.id
Join table_b r on p.root = r.id
GROUP BY e.name, r.id
) q
GROUP BY q.id
) err on err.id = rs.id
) err2
I am attempting to join all comment tables (shards of comments each month) to a posts table. Is there a way for me to perform a union all before the inner join? Details on the union all operator can be found in the documentation here. My query with only 1 of the comments table is as follows:
SELECT c.score, c.body, c.link_id, c.parent_id, p.created_utc, c.created_utc
FROM [fh-bigquery:reddit_comments.2016_01] AS c
INNER JOIN [fh-bigquery:reddit_posts.full_corpus_201512] AS p
ON c.parent_id = p.name
WHERE SUBSTR(c.parent_id, 1, 2) = 't3'
ORDER BY c.score DESC
LIMIT 10
Replace
FROM [fh-bigquery:reddit_comments.2016_01] AS c
with
FROM (
SELECT score, body, link_id, parent_id, created_utc
FROM (TABLE_QUERY([fh-bigquery:reddit_comments],
'REGEXP_MATCH(table_id, r"\d{4}_\d{2}")'))
) AS c
Hope, this gives you idea
See more on Table wildcard functions and Regular expression functions
As Mikhail Berlyant pointed out in his answer, modifying the query as such accomplished what I needed.
SELECT c.score, c.body, c.link_id, c.parent_id, p.created_utc, c.created_utc, (c.created_utc - p.created_utc) AS time_diff
FROM (
SELECT *
FROM
[fh-bigquery:reddit_comments.2015_11],
[fh-bigquery:reddit_comments.2015_12],
[fh-bigquery:reddit_comments.2016_01],
) AS c
INNER JOIN [fh-bigquery:reddit_posts.full_corpus_201512] AS p
ON c.parent_id = p.name
WHERE SUBSTR(c.parent_id, 1, 2) = 't3'
ORDER BY c.score DESC
LIMIT 100
For each row from table tClass matching a given where clause,
join on the first row in tEv, sorted by time, where tEv.class_id = tClass.class_id
The following code throws the error
ORA-01799: a column may not be outer-joined to a subquery
select
c.class_id,
c.class_name,
e.start_time,
e.ev_id
from
tClass c
left join tEv e on (
e.ev_id = (
select
ss1.ev_id
from (
select
ed.ev_id
from
tEvDisp ed,
tEv e
where
ed.class_id = c.class_id
and ed.viewable = 'Y'
and ed.display_until > localtimestamp
and e.ev_id = ed.ev_id
order by
e.start_time
) ss1
where
rownum = 1
)
)
where
c.is_matching = 'Y';
How can this be rewritten to do what is described?
The above is for oracle, but needs to work in sqlite (substituting where necessary)
No idea about SQLite - that would need to be a separate question if this doesn't work - but for Oracle you could do something like this:
select c.class_id,
c.class_name,
e.start_time,
e.ev_id
from tClass c
left join (
select class_id, ev_id, start_time
from (
select ed.class_id,
ed.ev_id,
e.start_time,
row_number() over (partition by ed.class_id order by e.start_time) as rn
from tEvDisp ed
join tEv e on e.ev_id = ed.ev_id
where ed.viewable = 'Y'
and ed.display_until > localtimestamp
)
where rn = 1
) e on e.class_id = c.class_id
where c.is_matching = 'Y';
This uses a subquery which finds the most tEv data, using an analytic row_number() to identify the latest data for each class_id, which is restricted by the rn = 1 filter.
That subquery, consisting of at most one row per class_id, is then used the left outer join against tClass.
This sort of construct should get you what you need. You can fix the details.
select c.classid
, c.classname
, temp.maxstarttime
from tClass c left join (
select c.classid id
max(e.start_time) maxstarttime
from tClass join tEv on tEv.classId = tClass.ClassId
where whatever
group by c.classid) temp on c.classid = temp.id