Reputation: 647
I am trying to get Month To Date(MTD), Last month to Date (LMTD) and Last month (LM) computed from a table that looks like this. Date here is stored as an integer.
+----------+----------+-------+
| Category | Date | Amount|
+----------+----------+-------+
| A | 20210608 | 2000 |
+----------+----------+-------+
| A | 20210607 | 4000 |
+----------+----------+-------+
| A | 20210606 | 6000 |
+----------+----------+-------+
| A | 20210605 | 8000 |
+----------+----------+-------+
| B | 20210608 | 1000 |
+----------+----------+-------+
| B | 20210607 | 5000 |
+----------+----------+-------+
| B | 20210606 | 5000 |
+----------+----------+-------+
| B | 20210605 | 5000 |
+----------+----------+-------+
| C | 20210608 | 5000 |
+----------+----------+-------+
| C | 20210607 | 5000 |
+----------+----------+-------+
Now I am able to compute MTD values using the following syntax
SELECT Category
, date
, Amount
, SUM(Amount) OVER(PARTITION BY to_CHAR(date, 'YYYY-MM'),Category ORDER BY date DESC) MTD
FROM table
But I am lost when trying to compute LMTD and LM values. LMTD is the window sum(Amount) from May 1st to May 10th, and LM is the sum for entire May. LMTD is useful to compare with MTD to see if MTD is doing better or not. The challenge is that it has to sum for previous month till exactly from may 1st to may 10th. Is there a way to compute LMTD and LM values using sql ?
+----------+----------+-------+-------+-------+-------+
| Category | Date | Amount| MTD | LMTD | LM |
+----------+----------+-------+-------+-------+-------+
| A | 20210608 | 2000 | 20000 | 16000 | 50000 |
+----------+----------+-------+-------+-------+-------+
| A | 20210607 | 4000 | 18000 | 14000 | 50000 |
+----------+----------+-------+-------+-------+-------+
| A | 20210606 | 6000 | 14000 | 12000 | 50000 |
+----------+----------+-------+-------+-------+-------+
| A | 20210605 | 8000 | 8000 | 10000 | 50000 |
+----------+----------+-------+-------+-------+-------+
| B | 20210608 | 1000 | 16000 | 24000 | 60000 |
+----------+----------+-------+-------+-------+-------+
| B | 20210607 | 5000 | 15000 | 18000 | 60000 |
+----------+----------+-------+-------+-------+-------+
| B | 20210606 | 5000 | 10000 | 12000 | 60000 |
+----------+----------+-------+-------+-------+-------+
| B | 20210605 | 5000 | 5000 | 6000 | 60000 |
+----------+----------+-------+-------+-------+-------+
| C | 20210608 | 5000 | 10000 | 12000 | 40000 |
+----------+----------+-------+-------+-------+-------+
| C | 20210607 | 5000 | 5000 | 6000 | 40000 |
+----------+----------+-------+-------+-------+-------+
Upvotes: 0
Views: 538
Reputation: 1271171
The simplest method might be a lateral join:
select t.*, t2.*
from t left join lateral
(select sum(t2.amount) as lmon,
sum(t2.amount) filter (where extract(day from t2.date) <= extract(day from t.date)) as lmtd
from t t2
where t2.date < date_trunc('month', t.date) and
t2.date >= date_trunc('month', t.date) - interval '1 month'
) t2
on 1=1;
Upvotes: 1