This code gets the number of ids that that show up for each month with in the year.
x
WITH t1 as (SELECT * FROM daily WHERE EVENT_DATE BETWEEN DATE '2019-01-01' and DATE '2019-12-31'),
SELECT ID, COUNT(ID) AS monthly_count, TO_CHAR(EVENT_DATE, 'YYYY-MM') as mon_yy
FROM t1 GROUP BY ID, TO_CHAR(EVENT_DATE, 'YYYY-MM')
This is the result i get:
1 |2019-01 |152
1 |2019-02 |127
1 |2019-03 |186
1 |2019-04 |47
1 |2019-05 |31
1 |2019-06 |46
1 |2019-07 |34
1 |2019-08 |22
1 |2019-09 |17
1 |2019-10 |22
1 |2019-11 |12
1 |2019-12 |16
2 |2019-01 |84930842
2 |2019-02 |69685158
2 |2019-03 |109122032
2 |2019-04 |114767006
2 |2019-05 |116766004
2 |2019-06 |197809839
2 |2019-07 |205065236
2 |2019-08 |383143170
2 |2019-09 |244118916
2 |2019-10 |210451973
2 |2019-11 |142372447
2 |2019-12 |63189538
3 |2019-01 |4361080
3 |2019-02 |5679732
3 |2019-03 |10101952
I want to get the yearly average of each ID, and the overall count. The results will look like this:
ID| YEAR | OVER_ALL_COUNT| AVG
1| 2019 | 712 | 59.33
2| 2019 | 20936849 | 161185684.6
3| 2019 | 14255773 | 2177532.2
Advertisement
Answer
You can add another level of aggregation:
select id, to_char(event_month, 'yyyy') event_year, sum(cnt) overall_count, avg(cnt) average_count
from (
select id, trunc(event_date, 'month') event_month, count(*) cnt
from daily
where event_date >= date '2019-01-01' and event_date < '2020-01-01'
group by id, trunc(event_date, 'month')
) t
group by id, to_char(event_month, 'yyyy')
Notes:
you don’t actually need a CTE to pre-filter the data: this can be done directly in the first aggregation query
I changed the filtering logic to use half-open intervals; if your dates have time components that are other than
'00:00:00'
, then this avoids filtering out the last day of the month (and if not, it doesn’t hurt either)