按父级对没有共同组的每 X 行求和

dav*_*vey 1 sql-server t-sql sql-server-2016

试图按父项对没有共同组的每 X 行求和

declare @temp table(Row_ID int, amt DECIMAL(18,2))
insert into @temp values(1, 20)
insert into @temp values(2, 24)
insert into @temp values(3, 20)
insert into @temp values(4, 15)
insert into @temp values(5, 15)
Run Code Online (Sandbox Code Playgroud)

如果 X 行是 2,那么所需的结果是对 2 行求和并将总数放在行旁边。所以前 2 行总计为 44 ,接下来的 2 行为 35 ,剩下的 1 行总计为 15

Row_ID  amt     tot
1       20.00    44.00
2       24.00    44.00
3       20.00    35.00
4       15.00    35.00
5       15.00    15.00
Run Code Online (Sandbox Code Playgroud)

如果 X 行是 3,那么所需的结果

Row_ID  amt     tot
1       20.00    64.00
2       24.00    64.00
3       20.00    64.00
4       15.00    30.00
5       15.00    30.00
Run Code Online (Sandbox Code Playgroud)

如果 X 行为 1,则所需结果

Row_ID  amt     tot
1       20.00    20.00
2       24.00    24.00
3       20.00    20.00
4       15.00    15.00
5       15.00    15.00
Run Code Online (Sandbox Code Playgroud)

ype*_*eᵀᴹ 8

一种方法是将行分成组/分区 - 使用简单的数学(整数除法)并对over分区进行分组。我假设这些Row_ID值是UNIQUE.

如果 - 不太可能但如果 -Row_ID值中没有间隙并且它们从 开始1,那么我们可以使用简单的:

select row_id, amt,
       sum = sum(amt) over (partition by (row_id-1)/@GroupSize)
from t ;
Run Code Online (Sandbox Code Playgroud)

但由于这不太可能 - 值可能来自IDENTITY列或 a SEQUENCE,它们不能保证无间隙序列 - 我们必须创建一个无间隙序列,其中ROW_NUMBER()

with c as
  ( select row_id, amt,
           grp = (row_number() over (order by row_id) - 1) / @GroupSize
    from t
  )
select row_id, amt,
       sum = sum(amt) over (partition by grp)
from c ;
Run Code Online (Sandbox Code Playgroud)

dbfiddle.uk 中测试:

create table t 
(Row_ID int, amt DECIMAL(18,2)
) ;
GO
Run Code Online (Sandbox Code Playgroud)
?
insert into t values
  (1, 20),
  (2, 24),
  (3, 20),
  (4, 15),
  (5, 15) ;
GO
Run Code Online (Sandbox Code Playgroud)
5 行受影响
with c as
  ( select row_id, amt,
           grp = (row_number() over (order by row_id) - 1) / 2
    from t
  )
select row_id, amt,
       sum = sum(amt) over (partition by grp)
from c ;
GO
Run Code Online (Sandbox Code Playgroud)
row_id | amt | 和  
-----: | :---- | :----
     1 | 20.00 | 44.00
     2 | 24.00 | 44.00
     3 | 20.00 | 35.00
     4 | 15.00 | 35.00
     5 | 15.00 | 15.00
with c as
  ( select row_id, amt,
           grp = (row_number() over (order by row_id) - 1) / 3
    from t
  )
select row_id, amt,
       sum = sum(amt) over (partition by grp)
from c ;
GO
Run Code Online (Sandbox Code Playgroud)
row_id | amt | 和  
-----: | :---- | :----
     1 | 20.00 | 64.00
     2 | 24.00 | 64.00
     3 | 20.00 | 64.00
     4 | 15.00 | 30.00
     5 | 15.00 | 30.00

为了使行数参数化,您只需要将grp表达式中的除数替换为参数/变量引用:

grp = (row_number() over (order by row_id) - 1) / @GroupSize
Run Code Online (Sandbox Code Playgroud)

因此,在调用查询时传递参数值。

  • `sum2 = case when count(*) over (partition by grp) = @GroupSize then sum(amt) over (partition by grp) else 0 end` (2认同)