I’m working with table, its structure looks like this:
- from_date
DATE %Y-%m-%d
- to_date
DATE %Y-%m-%d
- person
VARCHAR
- tax
INT
Table shows that in period between date_from
and date_to
for such person
there was such tax
The whole point is that these periods can intersect and activities can sum. Roughly speaking, here is an example of a table:
date_from | date_to | person | tax |
---|---|---|---|
2020-01-30 | 2020-02-02 | person1 | 20 |
2020-01-30 | 2020-01-31 | person1 | 10 |
2020-02-01 | 2020-02-03 | person1 | 15 |
And I need a table with structure:
- date
DATE %Y-%m-%d
- person
VARCHAR
- tax
INT
where I get tax
aggregated for every date
for every person
and it will be look like this
date | person | tax |
---|---|---|
2020-01-30 | person1 | 30 |
2020-01-31 | person1 | 30 |
2020-02-01 | person1 | 35 |
2020-02-02 | person1 | 35 |
2020-02-03 | person1 | 15 |
Hope I was able to explain in an understandable way what I want.
Below the code I tried. But recursive approach does not solve the problem because the table has about 5 millions rows
WITH cte AS ( SELECT person, date_from, date_to, tax, date_from AS report_date FROM my_table WHERE date_from >= @date_from AND date_to < @date_to UNION ALL SELECT person, date_from, date_to, tax, DATEADD(DAY, 1, report_date) AS report_date FROM cte WHERE report_date < date_to ) SELECT person, report_date, SUM(tax) tax FROM cte GROUP BY person, report_date
Advertisement
Answer
You need a list of dates consisting of all start date, end date and end date + 1 in your table. Then calculate running sum such that:
- On start date the tax is added to sum
- On end date the tax remains unchanged
- On end date + 1 the tax is removed from sum
A group by is needed to compact rows having same date into one row.
WITH cte AS ( SELECT person, ca.* FROM t CROSS APPLY (VALUES (date_from, tax), (date_to, 0), (DATEADD(DAY, 1, date_to), -tax) ) AS ca(date, value) ) SELECT person, date, SUM(SUM(value)) OVER ( PARTITION BY person ORDER BY date ) AS tax_value FROM cte GROUP BY person, date ORDER BY person, date
person | date | tax_value |
---|---|---|
person1 | 2020-01-30 | 30 |
person1 | 2020-01-31 | 30 |
person1 | 2020-02-01 | 35 |
person1 | 2020-02-02 | 35 |
person1 | 2020-02-03 | 15 |
person1 | 2020-02-04 | 0 |