If i have a result set like this where i want the running total to be present in every ppid. for example plan_id 00-peb17A doesn't have any transactions for ppid 388, so the record is null. I want to be able to find a way to have the previous rt amount carry over even if there were no transactions for that ppid.
Right now I'm placing a group by query in a cte and computing a running total using the over clause.
WITH cte AS
(
SELECT plan_id, ppid,
SUM(amount) AS Assets
FROM #assets
GROUP BY plan_id, ppid
--ORDER BY plan_id, ppid ASC
)
SELECT *,
SUM(cte.Assets) OVER(PARTITION BY cte.plan_id ORDER BY cte.ppid) AS rt
FROM cte
I'm thinking I could join the table with a numbers table to do some sort of cartesian product and attach a record to that table for every transaction. But I'm really not sure how else to explain it. Here is the original table I want to create the cumulative sum for.
| plan_id | ppid | amount |
| ------- | ---- | ------ |
| 00-PEB17A | 386 | 20 |
| 00-PEB17A | 386 | 15 |
| 00-PEB17A | 387 | 5 |
| 00-PEB17A | 387 | 10 |
| 00-PEB17A | 389 | 20 |
| 01-ARS20B | 386 | 5 |
| 01-ARS20B | 386 | 10 |
| 01-ARS20B | 386 | 50 |
| 01-ARS20B | 387 | 30 |
| 01-ARS20B | 388 | 5 |
This is the result set I am getting
| plan_id | ppid | Assets | rt |
| --------- | ------ | ------ | --- |
| 00-PEB17A | 386 | 35 | 35 |
| 00-PEB17A | 387 | 15 | 50 |
| 00-PEB17A | 389 | 20 | 70 |
| 01-ARS20B | 386 | 65 | 65 |
| 01-ARS20B | 387 | 30 | 95 |
| 01-ARS20B | 388 | 5 | 100 |
I would like to get this result set where since ppid 388 is missing from plan id 00-PEB17A, the running total carries through. So if it is null, the put 0 but still continue the total.
| plan_id | ppid | Assets | rt |
| --------- | ------ | ------ | --- |
| 00-PEB17A | 386 | 35 | 35 |
| 00-PEB17A | 387 | 15 | 50 |
| 00-PEB17A | 388 | 0 | 50 |
| 00-PEB17A | 389 | 20 | 70 |
| 01-ARS20B | 386 | 65 | 65 |
| 01-ARS20B | 387 | 30 | 95 |
| 01-ARS20B | 388 | 5 | 100 |
Still haven't tried @ValNik recursive cte solution, but arrived at my own solution using a join with the numbers table and multiple cte's to get to the final running total. Here it is, would appreciate some feedback.
WITH a AS
(
SELECT *
FROM #assets
CROSS JOIN #numbers
),
combine AS
(
SELECT a.plan_id, a.n
FROM a
RIGHT OUTER JOIN #numbers AS n
ON n.n = a.ppid
),
dist AS
(
SELECT DISTINCT combine.plan_id, combine.n
FROM combine
),
new_asset_list AS
(
SELECT dist.plan_id, dist.n, ISNULL(ass.amount, 0) AS assets
FROM dist
LEFT OUTER JOIN #assets AS ass
ON ass.plan_id = dist.plan_id
AND ass.ppid = dist.n
),
grouped AS
(
SELECT nal.plan_id, nal.n, SUM(nal.assets) AS Assets
FROM new_asset_list AS nal
GROUP BY nal.plan_id, nal.n
)
SELECT *,
SUM(g.Assets) OVER(PARTITION BY g.plan_id ORDER BY g.n) AS rt
FROM grouped AS g
Numbers table as requested
CREATE TABLE #numbers
(
n INT
)
INSERT INTO #numbers
(
n
)
VALUES ( 386 ), ( 387 ), ( 388 ), ( 389 )
1条答案
按热度按时间3npbholx1#
See example with recusive CTE
maxrecursion=100 is default value. You can set this option to value enough for max missing range of ppid in table.
simple short query
Example with numbers table
Numbers table mast contain enough numbers for max missing range in table.