Reputation: 772
I have the following table on a Postgres server that is consistently updated with new dates (with the oldest date being 3 years ago) but for sake of simplicity, let's just bring up 3 records:
id date1 date2 date3
1245 01/04/2018 05/04/2018 03/05/2018
1255 01/04/2018 01/06/2018 04/06/2018
1231 03/05/2018 07/05/2018 07/06/2018
1234 01/04/2017 01/04/2017 01/06/2018
I would like to create an sql view that will give me a total count of units per type of date
month date1 date2 date3
Jun 0 1 3
May 1 1 1
Apr 2 1 0
Apr17 1 1 0
Is there a simple way to do that? My sql so far looks like
CREATE OR REPLACE VIEW monthly_view
AS
SELECT row_number() OVER (ORDER BY b.id) AS id,
'month',
count(*) as date1,
count(*) as date2,
count(*) as date3
FROM mytable b
GROUP BY month
ORDER BY month desc
But obviously doesn't work
Upvotes: 1
Views: 102
Reputation: 1269623
Start by generating the months. Then I think correlated subqueries are a simple way of doing the calculation:
select v.mon,
(select count(*)
from mytable t
where to_char(date1, 'mon') = v.mon
) as date1,
(select count(*)
from mytable t
where to_char(date2, 'mon') = v.mon
) as date2,
(select count(*)
from mytable t
where to_char(date3, 'mon') = v.mon
) as date3
from (values ('jun', 6), ('may', 5), ('apr', 4)
) v(mon, mm)
order by mm desc;
EDIT:
Although the above should be pretty reasonable, the following might have better performance:
select mon, sum( (which = 1)::int ) as date1, sum( (which = 2)::int ) as date2,
sum( (which = 3)::int ) as date3
from t cross join lateral
(values (1, to_char(date1, 'mon'), extract(month from date1)),
(2, to_char(date2, 'mon'), extract(month from date2)),
(3, to_char(date3, 'mon'), extract(month from date3))
) v(which, mon, mm)
group by mon, mm
order by mm desc;
Here is a rextester.
Upvotes: 1
Reputation: 189
Tested!
Luffydude, you want to do a bad thing, but that is solution ;)
--all months with allmonths as ( select to_char(date1, 'TMmon') as mm from tmp_a union select to_char(date2, 'TMmon') as mm from tmp_a union select to_char(date3, 'TMmon') as mm from tmp_a ), --count_in_date1 count_in_date1 as ( select t1.mm, count(t2.date1) as count_in_date1 from allmonths t1 left join tmp_a t2 on to_char(t2.date1, 'TMmon') = t1.mm group by t1.mm ), --count_in_date2 count_in_date2 as ( select t1.mm, count(t2.date2) as count_in_date2 from allmonths t1 left join tmp_a t2 on to_char(t2.date2, 'TMmon') = t1.mm group by t1.mm ), --count_in_date3 count_in_date3 as ( select t1.mm, count(t2.date3) as count_in_date3 from allmonths t1 left join tmp_a t2 on to_char(t2.date3, 'TMmon') = t1.mm group by t1.mm ) --join all count together select t1.mm, count_in_date1, count_in_date2, count_in_date3 from count_in_date1 t1, count_in_date2 t2, count_in_date3 t3 where t1.mm=t2.mm and t1.mm=t3.mm
Upvotes: 2