Reputation: 9727
I have a table of users like this:
Table user
id | name | date
1 | alice | 2021-03-28
2 | bob | 2021-03-29
...
And a table with their contacts:
Table contact
id | user_id | contact | has_profile
1 | 1 | facebook | 1
2 | 1 | gmail | 1
3 | 1 | yahoo | 0
4 | 2 | facebook | 0
5 | 2 | gmail | 1
6 | 2 | yahoo | 1
...
I want to write a query that aggregates average rates of the contacts in different dates, so that the result should be:
date | facebook | gmail | yahoo
2021-03-29 | 0.7 | 0.82 | 0.15
2021-03-28 | 0.75 | 0.85 | 0.18
...
I could reach it by the query:
select
u."date",
avg(f.has_profile) as facebook,
avg(g.has_profile) as gmail,
avg(y.has_profile) as yahoo
from user u
join contact f on f.user_id = u.id and f.contact = 'facebook'
join contact g on g.user_id = u.id and g.contact = 'gmail'
join contact y on y.user_id = u.id and y.contact = 'yahoo'
group by u."date"
order by u."date" desc
But the point is that this query depends on the certain contact names in the table contact
, so if there are too many ones, the query is too long and complicated to modify. Is there a way to say to Postgresql to extract the names of the contacts automatically and to aggregate over them?
Upvotes: 0
Views: 41
Reputation: 23666
(JSON aggregate as requested in the comments)
SELECT
my_date,
jsonb_object_agg(contact, avg) -- 3
FROM (
SELECT
my_date,
contact,
AVG(has_profile) -- 2
FROM
contact c
JOIN users u ON c.user_id = u.id -- 1
GROUP BY my_date, contact
) s
GROUP BY my_date
date
and contact
Unrelated note: date
and user
are unrecommended names for database entities because they are reserved keywords. You have to handle them carefully (always use "
characters). It's better to rename these properly. Moreover, date is not very descriptive. Maybe login_date
or something
Upvotes: 1