'Aggregate monthly rows created date and ended date
I need to adapt a graph from the current BI implementation to an SQL one. This graph reflects the amount of requests received and each one of these requests have 3 fields that are relevant for this query: the id, created date and the end date.
The graph looks like this https://i.stack.imgur.com/NRIjr.png:
+----+--------------+-------------+
| ID | CREATE_DATE | END_DATE |
+----+--------------+-------------+
| | | |
| 1 | 2022-01-01 | 2022-02-10 |
| | | |
| 2 | 2022-01-03 | 2022-03-01 |
| | | |
| 3 | 2022-02-01 | 2022-04-01 |
| | | |
| 4 | 2022-03-01 | null |
+----+--------------+-------------+
So for this particular example we'd have something like this:
- January: active: 2 (requests 1 and 2), finished: 0;
- February: active 2 (requests 2, 3), finished 1 (request 1);
- March: active 2 (requests 3, 4) finished 1 (request 2)
So for each month I want the active requests for that particular month (those that their ended date goes after that particular month or is null) and the requests that finished during that month (this one might be split to another query, of course) I tried this query, but of course, it doesn't take into account the requests that ended in a particular month, and only gives me the cumulative sum
Edit: I forgot to mention that one of the requirements is that the beggining and end date of the graph might be set by the user. So maybe I want to see the months from April-2022 to April-2020 and see the 2 year behaviour!
WITH cte AS ( SELECT
date_trunc('month',
r.date_init) AS mon,
count(r.id) AS mon_sum
FROM
"FOLLOWUP"."CAT_REQUEST" r
GROUP BY
1 ) SELECT
to_char(mon,
'YYYY-mm') AS mon_text,
COALESCE(sum(c.mon_sum)
OVER (ORDER BY mon),
0) AS running_sum
FROM
generate_series('2022-01-01', '2023-12-25',
interval '1 month') mon
LEFT JOIN
cte c USING (mon)
ORDER BY
mon
Solution 1:[1]
I wrote query for you using some different business logic. But, result is will be same result which you needed. Sample query:
with month_list as (
select 1 as id, 'Yanuary' as mname union all
select 2 as id, 'Febriary' as mname union all
select 3 as id, 'Marth' as mname union all
select 4 as id, 'April' as mname union all
select 5 as id, 'May' as mname union all
select 6 as id, 'June' as mname union all
select 7 as id, 'Jule' as mname union all
select 8 as id, 'August' as mname union all
select 9 as id, 'September' as mname union all
select 10 as id, 'October' as mname union all
select 11 as id, 'November' as mname union all
select 12 as id, 'December' as mname
),
test_table as (
select
id,
create_date,
end_date,
extract(month from create_date) as month1,
extract(month from end_date) as month2
from
your_table
)
select
t1.mname,
count(*) as "actived"
from
month_list t1
inner join
test_table t2 on (t1.id >= t2.month1) and (t1.id < t2.month2)
group by
t1.id, t1.mname
order by
t1.id
/* --- Result:
mname actived
--------------------
Yanuary 2
Febriary 2
Marth 1
*/
Solution 2:[2]
PostgreSQL has many date & time functions and types.
I write some samples for you:
For example, in my samples function now()
our chosen date.
-- get previos 12 month from date (return timestampt)
select now() - '12 month'::interval as newdate
-- Return:
2021-04-03 18:22:48.344 +0400
-- if you need only date, you can cast this to date
select (now() - '12 month'::interval)::date as newdate
-- Return:
2021-04-03
-- generate data from previous 12 month to selected date increase by month:
SELECT t1.datelist::date
from generate_series
(
now()-'12 month'::interval,
now(),
'1 month'
)
AS t1(datelist)
-- Return:
2021-04-03
2021-05-03
2021-06-03
2021-07-03
2021-08-03
2021-09-03
2021-10-03
2021-11-03
2021-12-03
2022-01-03
2022-02-03
2022-03-03
2022-04-03
-- generate data from previous 12 month to selected date increase by month with extracting month names and year:
-- this sample may be as you needed.
SELECT
extract(year from t1.datelist) as "year",
TO_CHAR(t1.datelist, 'Month') as "month",
trim(TO_CHAR(t1.datelist, 'Month')) || '-' || trim(to_char(t1.datelist, 'yyyy')) as "formatted_date"
from generate_series
(
now()-'12 month'::interval,
now(),
'1 month'
)
AS t1(datelist)
-- Return:
year month formatted_date
------------------------------------
2021 April April-2021
2021 May May-2021
2021 June June-2021
2021 July July-2021
2021 August August-2021
2021 September September-2021
2021 October October-2021
2021 November November-2021
2021 December December-2021
2022 January January-2022
2022 February February-2022
2022 March March-2022
2022 April April-2022
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ramin Faracov |
Solution 2 | Ramin Faracov |