I am using oracle 19.24. I am debugging my SQL query and found some weird thing. Here are testing scripts:
create table test_payment
(
payment_date date,
payment_sum number
);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-03-2015', 'dd-mm-yyyy'), 149);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('28-10-2019', 'dd-mm-yyyy'), 15);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('28-10-2019', 'dd-mm-yyyy'), 117);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('25-11-2024', 'dd-mm-yyyy'), 27);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('12-09-2020', 'dd-mm-yyyy'), 369);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('30-07-2020', 'dd-mm-yyyy'), 199);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-08-2023', 'dd-mm-yyyy'), 118);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('02-04-2016', 'dd-mm-yyyy'), 48);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('20-09-2019', 'dd-mm-yyyy'), 239);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('11-05-2021', 'dd-mm-yyyy'), 78);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-02-2018', 'dd-mm-yyyy'), 265);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-01-2019', 'dd-mm-yyyy'), 89);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('30-12-2021', 'dd-mm-yyyy'), 175);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-04-2024', 'dd-mm-yyyy'), 249);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('30-06-2015', 'dd-mm-yyyy'), 125);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('30-06-2021', 'dd-mm-yyyy'), 3);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('15-02-2024', 'dd-mm-yyyy'), 55);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-04-2018', 'dd-mm-yyyy'), 30);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('11-11-2020', 'dd-mm-yyyy'), 259);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('11-06-2016', 'dd-mm-yyyy'), 279);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-10-2024', 'dd-mm-yyyy'), 5);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('08-02-2021', 'dd-mm-yyyy'), 35);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('21-09-2020', 'dd-mm-yyyy'), 58);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('02-01-2024', 'dd-mm-yyyy'), 38);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('26-09-2020', 'dd-mm-yyyy'), 76);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('15-07-2017', 'dd-mm-yyyy'), 44);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-07-2021', 'dd-mm-yyyy'), 14);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-10-2019', 'dd-mm-yyyy'), 159);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('29-03-2023', 'dd-mm-yyyy'), 118);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('19-11-2022', 'dd-mm-yyyy'), 135);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('25-12-2018', 'dd-mm-yyyy'), 19);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-12-2018', 'dd-mm-yyyy'), 45);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-05-2015', 'dd-mm-yyyy'), 14);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('04-03-2022', 'dd-mm-yyyy'), 35);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-03-2018', 'dd-mm-yyyy'), 74);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('07-06-2015', 'dd-mm-yyyy'), 129);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('08-08-2019', 'dd-mm-yyyy'), 51);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('20-12-2024', 'dd-mm-yyyy'), 6);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('03-03-2024', 'dd-mm-yyyy'), 69);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('14-04-2017', 'dd-mm-yyyy'), 5);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('16-07-2016', 'dd-mm-yyyy'), 35);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-11-2015', 'dd-mm-yyyy'), 115);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('28-12-2022', 'dd-mm-yyyy'), 135);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-06-2017', 'dd-mm-yyyy'), 45);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('31-08-2023', 'dd-mm-yyyy'), 327);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-06-2020', 'dd-mm-yyyy'), 69);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('17-10-2023', 'dd-mm-yyyy'), 189);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-12-2019', 'dd-mm-yyyy'), 225);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('22-02-2015', 'dd-mm-yyyy'), 25);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('15-02-2017', 'dd-mm-yyyy'), 199);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('06-03-2021', 'dd-mm-yyyy'), 5);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('28-03-2022', 'dd-mm-yyyy'), 79);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-02-2022', 'dd-mm-yyyy'), 219);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('09-06-2024', 'dd-mm-yyyy'), 30);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('30-04-2018', 'dd-mm-yyyy'), 369);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('15-06-2022', 'dd-mm-yyyy'), 209);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('12-07-2023', 'dd-mm-yyyy'), 499);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('26-11-2023', 'dd-mm-yyyy'), 130);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('01-10-2020', 'dd-mm-yyyy'), 149);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('12-12-2022', 'dd-mm-yyyy'), 15);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('02-11-2017', 'dd-mm-yyyy'), 175);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-09-2018', 'dd-mm-yyyy'), 255);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('11-08-2020', 'dd-mm-yyyy'), 255);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('21-01-2019', 'dd-mm-yyyy'), 179);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('07-01-2015', 'dd-mm-yyyy'), 105);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('26-09-2017', 'dd-mm-yyyy'), 48);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-09-2021', 'dd-mm-yyyy'), 115);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-08-2023', 'dd-mm-yyyy'), 659);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('10-06-2019', 'dd-mm-yyyy'), 13);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('10-09-2015', 'dd-mm-yyyy'), 595);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('17-03-2015', 'dd-mm-yyyy'), 68);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('10-04-2017', 'dd-mm-yyyy'), 71);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('06-04-2023', 'dd-mm-yyyy'), 28);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('01-04-2018', 'dd-mm-yyyy'), 179);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('02-08-2015', 'dd-mm-yyyy'), 159);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('14-11-2023', 'dd-mm-yyyy'), 1);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('25-06-2020', 'dd-mm-yyyy'), 125);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('09-04-2023', 'dd-mm-yyyy'), 51);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('11-10-2017', 'dd-mm-yyyy'), 69);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('17-03-2022', 'dd-mm-yyyy'), 229);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('09-08-2021', 'dd-mm-yyyy'), 29);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-06-2017', 'dd-mm-yyyy'), 38);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('08-07-2024', 'dd-mm-yyyy'), 249);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('15-11-2022', 'dd-mm-yyyy'), 65);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('05-12-2018', 'dd-mm-yyyy'), 69);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('26-10-2018', 'dd-mm-yyyy'), 129);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('20-06-2024', 'dd-mm-yyyy'), 35);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('29-11-2020', 'dd-mm-yyyy'), 29);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('18-06-2022', 'dd-mm-yyyy'), 209);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('25-04-2024', 'dd-mm-yyyy'), 119);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('12-12-2020', 'dd-mm-yyyy'), 299);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('03-02-2024', 'dd-mm-yyyy'), 238);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('27-06-2016', 'dd-mm-yyyy'), 89);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('28-09-2023', 'dd-mm-yyyy'), 69);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('13-04-2021', 'dd-mm-yyyy'), 20);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('15-10-2016', 'dd-mm-yyyy'), 59);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('12-09-2016', 'dd-mm-yyyy'), 15);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('09-10-2018', 'dd-mm-yyyy'), 149);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('21-10-2016', 'dd-mm-yyyy'), 85);
insert into test_payment (PAYMENT_DATE, PAYMENT_SUM)
values (to_date('28-06-2019', 'dd-mm-yyyy'), 24);
This query returns 12482, nothing special
select
sum(for_total)
from (
select
extract(year from payment_date) "year",
payment_sum for_total,
payment_sum
from test_payment
)
But this query returns 9003!
select
sum(for_total)
from (
select
extract(year from payment_date) "year",
payment_sum for_total,
payment_sum
from test_payment
)
pivot
(
sum(payment_sum) for "year" in (2020,2021,2022,2023,2024)
)
The idea obviously is this:
select
sum("2020"),sum("2021"),sum("2022"),sum("2023"),sum("2024"),
sum(for_total)
from (
select
extract(year from payment_date) "year",
payment_sum for_total,
payment_sum
from test_payment
)
pivot
(
sum(payment_sum) for "year" in (2020,2021,2022,2023,2024)
)
Get sum for last 5 years and grand total (not only for 5 year, total sum) at the end. And by the way, sum for last 5 years are 7000.
Why pivot changes total sum? It seems that I don't know or don't understand something about pivot.
If you have the simplified data-set:
create table test_payment( payment_date, payment_sum ) AS
SELECT DATE '2020-01-01', 100 FROM DUAL UNION ALL
SELECT DATE '2021-01-01', 100 FROM DUAL UNION ALL
SELECT DATE '2022-01-01', 100 FROM DUAL UNION ALL
SELECT DATE '2022-01-01', 100 FROM DUAL UNION ALL
SELECT DATE '2023-01-01', 100 FROM DUAL UNION ALL
SELECT DATE '2024-01-01', 100 FROM DUAL UNION ALL
SELECT DATE '2020-01-01', 200 FROM DUAL UNION ALL
SELECT DATE '2021-01-01', 200 FROM DUAL UNION ALL
SELECT DATE '2024-01-01', 200 FROM DUAL UNION ALL
SELECT DATE '2023-01-01', 300 FROM DUAL;
Then:
select *
from (
select extract(year from payment_date) AS year,
payment_sum AS for_total,
payment_sum
from test_payment
)
pivot (
sum(payment_sum) for year in (2020,2021,2022,2023,2024)
);
Will PIVOT the year into columns and will GROUP BY all the columns that are not mentioned in the PIVOT clause, which is for_total, so it is the same as:
SELECT for_total,
SUM(CASE year WHEN 2020 THEN payment_sum END) AS "2020",
SUM(CASE year WHEN 2021 THEN payment_sum END) AS "2021",
SUM(CASE year WHEN 2022 THEN payment_sum END) AS "2022",
SUM(CASE year WHEN 2023 THEN payment_sum END) AS "2023",
SUM(CASE year WHEN 2024 THEN payment_sum END) AS "2024"
FROM (SELECT EXTRACT(year FROM payment_date) AS year,
payment_sum AS for_total,
payment_sum
FROM test_payment)
GROUP BY for_total;
Which both output:
| FOR_TOTAL | 2020 | 2021 | 2022 | 2023 | 2024 |
|---|---|---|---|---|---|
| 100 | 100 | 100 | 200 | 100 | 100 |
| 200 | 200 | 200 | 200 | ||
| 300 | 300 |
You can see that by having the FOR_TOTAL column, any values that appear multiple times across the years are totalled correctly in the relative years but the FOR_TOTAL value is the unique value and will not include duplicates; which is why you are under-counting.
You are effectively performing the calculation:
SELECT SUM(DISTINCT payment_sum) AS for_total
FROM test_payment;
What you want to do is to not include FOR_TOTAL and then generate the total from the other columns:
SELECT "2020", "2021", "2022", "2023", "2024",
"2020" + "2021" + "2022" + "2023" + "2024" AS for_total
FROM (
SELECT EXTRACT(YEAR FROM payment_date) AS year,
payment_sum
FROM test_payment
)
PIVOT (
SUM(payment_sum) FOR year IN (2020,2021,2022,2023,2024)
);
Note: This will not total any dates outside the range of years in your pivot.
Which outputs:
| 2020 | 2021 | 2022 | 2023 | 2024 | FOR_TOTAL |
|---|---|---|---|---|---|
| 300 | 300 | 200 | 400 | 300 | 1500 |
Or:
SELECT SUM(CASE year WHEN 2020 THEN payment_sum END) AS "2020",
SUM(CASE year WHEN 2021 THEN payment_sum END) AS "2021",
SUM(CASE year WHEN 2022 THEN payment_sum END) AS "2022",
SUM(CASE year WHEN 2023 THEN payment_sum END) AS "2023",
SUM(CASE year WHEN 2024 THEN payment_sum END) AS "2024",
SUM(payment_sum) AS for_total
FROM (
SELECT EXTRACT(YEAR FROM payment_date) AS year,
payment_sum
FROM test_payment
-- WHERE payment_date >= DATE '2020-01-01'
-- AND payment_date < DATE '2025-01-01'
)
Note: This will total all dates, including those outside the range of years in your pivot. If you want to only total those within the range of years then uncomment the WHERE filters.
fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With