SQL - Getting Sum of 'X' Consecutive Values where X is an Integer in another Row (With Categories)

与世无争的帅哥 提交于 2020-12-14 06:30:36

问题


Say for example, I wanted to SUM all the values from the current row until the provided count. See table below:

For example:

  • Category A, Row 1: 10+15+25 = 50 (because it adds Rows 1 to 3 due to Count)
  • Category A, Row 2: 15+25+30+40 = 110 (because it adds Rows 2 to 5 due to count)
  • Category A, Row 5: 40+60 = 100 (because it Adds Rows 5 and 6. Since the count is 5, but the category ends at Row 6, so instead of that, it sums all available data which is Rows 5 and 6 only, thus having a value of 100.
  • Same goes for Category B.

How do I do this?


回答1:


You can do this using window functions:

with tt as (
      select t.*,
             sum(quantity) over (partition by category order by rownumber) as running_quantity,
             max(rownumber) over (partition by category) as max_rownumber
      from t
     )
select tt.*,
       coalesce(tt2.running_quantity, ttlast.running_quantity) - tt.running_quantity + tt.quantity
from tt left join
     tt tt2
     on tt2.category = tt.category and
        tt2.rownumber = tt.rownumber + tt.count - 1 left join
     tt ttlast
     on ttlast.category = tt.category and
        ttlast.rownumber = ttlast.max_rownumber
order by category, rownumber;

I can imagine that under some circumstances this would be much faster -- particularly if the count values are relatively large. For small values of count, the lateral join is probably faster, but it is worth checking if performance is important.

Actually, a pure window functions approach is probably the best approach:

with tt as (
      select t.*,
             sum(quantity) over (partition by category order by rownumber) as running_quantity
      from t
     )
select tt.*,
       (coalesce(lead(tt.running_quantity, tt.count - 1) over (partition by tt.category order by tt.rownumber),
                 first_value(tt.running_quantity) over (partition by tt.category order by tt.rownumber desc)
                ) - tt.running_quantity + tt.quantity
       )
from tt
order by category, rownumber;

Here is a db<>fiddle.




回答2:


Try this:

DECLARE @DataSource TABLE 
(
    [Category] CHAR(1)
   ,[Row Number] BIGINT
   ,[Quantity] INT
   ,[Count] INT
);

INSERT INTO @DataSource ([Category], [Row Number], [Quantity], [Count])
VALUES ('A', 1, 10, 3)
      ,('A', 2, 15, 4)
      ,('A', 3, 25, 2)
      ,('A', 4, 30, 1)
      ,('A', 5, 40, 5)
      ,('A', 6, 60, 2)
      --
      ,('B', 1, 12, 2)
      ,('B', 2, 13, 3)
      ,('B', 3, 17, 1)
      ,('B', 4, 11, 2)
      ,('B', 5, 10, 5)
      ,('B', 6, 7, 3);

SELECT *
FROM @DataSource E
CROSS APPLY
(
    SELECT SUM(I.[Quantity])
    FROM @DataSource I
    WHERE I.[Row Number] <= E.[Row Number] + E.[Count] - 1
        AND I.[Row Number] >= E.[Row Number]
        AND E.[Category] = I.[Category]
) DS ([Sum]);



来源:https://stackoverflow.com/questions/64853208/sql-getting-sum-of-x-consecutive-values-where-x-is-an-integer-in-another-row

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!