I can simply use LAG()
to calculate the percentage change from my table (see below) of this month compared to the data 3 months ago or 1 year ago.
But now, I want to get this result: calculate the sum of each quarter, and then get the percentage change (Q1 of the following year needs to be calculated with reference to Q4 of the previous year.)
For example:
year | quarter | total_num | quarter_change_pct |
---|---|---|---|
2021 | 1 | 1088030 | 0.00% |
2021 | 2 | 1077857 | -0.93% |
2021 | 3 | 1048368 | -2.74% |
2021 | 4 | 992279 | -5.35% |
2022 | 1 | 1026123 | 3.41% |
2022 | 2 | 1074024 | 4.67% |
2022 | 3 | 1054501 | -1.82% |
2022 | 4 | 1080568 | 2.47% |
2023 | 1 | 1001410 | -7.33% |
2023 | 2 | 961672 | -3.97% |
2023 | 3 | 979835 | 1.89% |
2023 | 4 | 982167 | 0.24% |
I don’t know how to solve this problem, it would be greatly appreciated if anyone can help.(BTW, the database I use supports the majority of PostgreSQL syntax, so you can also use PostgreSQL for demo, thanks!)
sample data:
create table tb1(
date date,
num int
);
insert into tb1 values
('2021-01-31', 359738),
('2021-02-28', 378564),
('2021-03-31', 349728),
('2021-04-30', 368945),
('2021-05-31', 321456),
('2021-06-30', 387456),
('2021-07-31', 310567),
('2021-08-31', 342189),
('2021-09-30', 395612),
('2021-10-31', 278945),
('2021-11-30', 365478),
('2021-12-31', 347856),
('2022-01-31', 319478),
('2022-02-28', 382456),
('2022-03-31', 324189),
('2022-04-30', 395612),
('2022-05-31', 367845),
('2022-06-30', 310567),
('2022-07-31', 382456),
('2022-08-31', 347856),
('2022-09-30', 324189),
('2022-10-31', 395612),
('2022-11-30', 319478),
('2022-12-31', 365478),
('2023-01-31', 302856),
('2023-02-28', 334531),
('2023-03-31', 364023),
('2023-04-30', 334534),
('2023-05-31', 313678),
('2023-06-30', 313460),
('2023-07-31', 357281),
('2023-08-31', 314578),
('2023-09-30', 307976),
('2023-10-31', 304567),
('2023-11-30', 311378),
('2023-12-31', 366222);
My table looks like this(simplified):
date | num |
---|---|
2021-01-31 | 359738 |
2021-02-28 | 378564 |
2021-03-31 | 349728 |
2021-04-30 | 368945 |
2021-05-31 | 321456 |
2021-06-30 | 387456 |
2021-07-31 | 310567 |
2021-08-31 | 342189 |
2021-09-30 | 395612 |
2021-10-31 | 278945 |
2021-11-30 | 365478 |
2021-12-31 | 347856 |
2022-01-31 | 319478 |
2022-02-28 | 382456 |
2022-03-31 | 324189 |
2022-04-30 | 395612 |
2022-05-31 | 367845 |
2022-06-30 | 310567 |
2022-07-31 | 382456 |
2022-08-31 | 347856 |
2022-09-30 | 324189 |
2022-10-31 | 395612 |
2022-11-30 | 319478 |
2022-12-31 | 365478 |
2023-01-31 | 302856 |
2023-02-28 | 334531 |
2023-03-31 | 364023 |
2023-04-30 | 334534 |
2023-05-31 | 313678 |
2023-06-30 | 313460 |
2023-07-31 | 357281 |
2023-08-31 | 314578 |
2023-09-30 | 307976 |
2023-10-31 | 304567 |
2023-11-30 | 311378 |
2023-12-31 | 366222 |
3
Answers
You have to use LAG and Quarter function to solve the issue in ProgreSQL.
QUARTER function return one of the following values:
LAG() function is a powerful window function that allows you to access data from a previous row within the same result set. It’s particularly useful for comparing values in the current row with values in the preceding row.
Finally, to get your result set the SQL script will be .
Implement this work on PostgreSQL 17.
Thanks
This query may be a little complicated, but the result meets your requirements. I hope it can help you.
test on PostgreSQL 16: https://dbfiddle.uk/7W1SW7KH
),
quarterly_changes AS (
SELECT
quarter,
total_amount,
LAG(total_amount) OVER (ORDER BY quarter) AS previous_total
FROM quarterly_sums
)
SELECT
EXTRACT(YEAR FROM quarter) AS year,
EXTRACT(QUARTER FROM quarter) AS year,
total_amount,
COALESCE(previous_total,0) as previous,
CASE
WHEN previous_total<>0 THEN
round(((total_amount – previous_total)/previous_total)*100,2)
ELSE
0
END AS percentage_change
FROM quarterly_changes
ORDER BY quarter;
You find the Quaterly amount and Previous Quarter amount from the 1st and 2nd cte (using LAG) and then calcualte the percentage change.