I am migrating some legacy code from an Oracle DB to an SQL Server DB. I have come along this piece of code, with the purpose of calculating the cumulative amount over the last 6 months/ year, for each record/group:
select
a,b,c,d,e,trunc(record_date, 'MM'),
sum(sum(amount)) over(
partition by a, b, c, d
order by trunc(record_date, 'MM')
range between interval 5 month preceding and current row) semester_amount,
sum(sum(amount)) over(
partition by a, b, c, d
order by trunc(record_date, 'MM')
range between interval '11' month preceding and current row) year_amount
from table
group by
a,b,c,d,e,trunc(record_date, 'MM')
My goal is to implement it in SQL Server where the date range in window partitions isn't available.
Here is a sample table I use for experimentation:
drop table if exists dbo.test_window_frames;
create table dbo.test_window_frames (
fielda char(1),
fieldb char(1),
fieldc char(2),
fieldd char(2),
fielde char(2),
amount int,
record_date date);
insert into dbo.test_window_frames (fielda, fieldb, fieldc, fieldd, fielde, amount, record_date)
values
('A', 'X', 'C1', 'D2', 'E2', 74, '2024-03-10'),
('A', 'X', 'C1', 'D2', 'E2', 34, '2024-03-12'),
('A', 'X', 'C1', 'D2', 'E2', 24, '2024-03-12'),
('A', 'X', 'C1', 'D2', 'E1', 24, '2024-03-25'),
('A', 'X', 'C1', 'D2', 'E1', 95, '2024-06-20'),
('A', 'X', 'C1', 'D2', 'E1', 81, '2024-06-27'),
('A', 'X', 'C1', 'D2', 'E1', 83, '2024-07-10'),
('A', 'X', 'C1', 'D2', 'E2', 73, '2024-07-27'),
('A', 'X', 'C1', 'D2', 'E2', 60, '2024-10-07'),
('A', 'X', 'C1', 'D2', 'E2', 50, '2024-10-07'),
('A', 'X', 'C2', 'D1', 'E1', 67, '2024-04-02'),
('A', 'X', 'C2', 'D1', 'E1', 69, '2024-12-04'),
('B', 'X', 'C1', 'D1', 'E1', 50, '2024-01-15'),
('B', 'X', 'C1', 'D1', 'E2', 30, '2024-02-20'),
('B', 'X', 'C2', 'D2', 'E1', 80, '2024-03-22'),
('B', 'X', 'C2', 'D2', 'E2', 90, '2024-05-10'),
('B', 'X', 'C1', 'D1', 'E1', 55, '2024-06-01'),
('B', 'X', 'C2', 'D2', 'E2', 20, '2024-07-19'),
('B', 'X', 'C1', 'D1', 'E2', 40, '2024-08-14'),
('B', 'X', 'C1', 'D1', 'E2', 5, '2024-08-14'),
('B', 'X', 'C1', 'D2', 'E1', 65, '2024-09-25'),
('B', 'X', 'C2', 'D1', 'E2', 35, '2024-10-12'),
('B', 'X', 'C2', 'D2', 'E1', 75, '2024-11-05');
The desired result is for each group (for example ('A', 'X', 'C1', 'D2', 'E2', '2024-03-01') the date is truncated) to have a row with the amount of the past 6 months and the past year since that group's date. (132 for both in this case)
Until now I tried my luck with subqueries:
select
t1.fielda,
t1.fieldb,
t1.fieldc,
t1.fieldd,
t1.fielde,
dateadd(month, datediff(month, 0, t1.record_date), 0) as reference_date,
(
select sum(t2.amount)
from dbo.test_window_frames t2
where t2.fielda = t1.fielda
and t2.fieldb = t1.fieldb
and t2.fieldc = t1.fieldc
and t2.fieldd = t1.fieldd
and t2.record_date between dateadd(month, -5, t1.record_date) and t1.record_date
) as semester_amount,
(
select sum(t2.amount)
from dbo.test_window_frames t2
where t2.fielda = t1.fielda
and t2.fieldb = t1.fieldb
and t2.fieldc = t1.fieldc
and t2.fieldd = t1.fieldd
and t2.record_date between dateadd(month, -11, t1.record_date) and t1.record_date
) as year_amount
from
dbo.test_window_frames t1
group by
t1.fielda, t1.fieldb, t1.fieldc, t1.fieldd, t1.fielde, dateadd(month, datediff(month, 0, t1.record_date), 0);
But I get the following error:
Column 'dbo.test_window_frames.record_date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Can you help me?
I attach the expected results that I believe are the output of the Oracle code, for the fieldA = 'A'.
| fielda | fieldb | fieldc | fieldd | fielde | reference_date | semester_amount | year_amount |
|---|---|---|---|---|---|---|---|
| A | X | C1 | D2 | E2 | 2024-03-01 | 132 | 132 |
| A | X | C1 | D2 | E1 | 2024-03-01 | 24 | 24 |
| A | X | C1 | D2 | E1 | 2024-06-01 | 200 | 200 |
| A | X | C1 | D2 | E1 | 2024-07-01 | 283 | 283 |
| A | X | C1 | D2 | E2 | 2024-07-01 | 205 | 205 |
| A | X | C1 | D2 | E2 | 2024-10-01 | 183 | 315 |
| A | X | C2 | D1 | E1 | 2024-04-01 | 67 | 67 |
| A | X | C2 | D1 | E1 | 2024-12-01 | 69 | 136 |