Sql server SQL Server:对有序集使用Windows函数
使用此示例数据集: ID POS QTY A B 32 1 50 1 2 28 2 200 1 2 12 3 300 2 2 16 4 400 1 2 98 5 500 3 1 56 6 600 2 2 33 7 700 2 2 ID POS数量A B 32 1 50 1 2 28 2 200 1 2 12 3 300 2 2 16 4 400 1 2 98 5 500 3 1 56 6 600 2 2 33 7 700 2 2 如何按组获取总和(数量)。分组基于POS订购的不同(A和B) 作为: ID POS数量A B总和(数量) 32 1 50 1 2 250第1组 28220012250第一组 123002300第2组 16 4 400 1 2 900第3组非1组 9855012900第3组不是1组 56 6 600 2 2 1300第4组不是第2组 33 7 700 2 2 1300第4组不是第2组 我尝试了不同的分区方法,但总是得到A和B相同的组Sql server SQL Server:对有序集使用Windows函数,sql-server,tsql,aggregate-functions,window-functions,Sql Server,Tsql,Aggregate Functions,Window Functions,使用此示例数据集: ID POS QTY A B 32 1 50 1 2 28 2 200 1 2 12 3 300 2 2 16 4 400 1 2 98 5 500 3 1 56 6 600 2 2 33 7 700 2 2
按POS订购很重要,因为相同的A和B构成不同的组。必须有更漂亮的方法来实现这一点,但这就是我现在得到的:
select t1.*, t2.sum_qty
from your_table t1
join
(
select a, b, sum(qty) as sum_qty
from your_table
group by a, b
) t2 on t1.a = t2.a and t1.b = t2.b
order by t1.pos
declare @t table (ID int,POS int,QTY int,A int,B int)
insert into @t(ID,POS,QTY,A,B) values
(32,1, 50,1,2), (28,2,200,1,2), (12,3,300,2,2), (16,4,400,1,2),
(98,5,500,1,2), (56,6,600,2,2), (33,7,700,2,2)
;With Origins as (
select t1.*
from @t t1
left join
@t t2
on
t1.POS = t2.POS + 1 and
t1.A = t2.A and
t1.B = t2.B
where t2.POS is null
)
select
t.*,SUM(t.QTY) OVER (PARTITION BY o.POS) as Qty
from
@t t
inner join
Origins o
on
t.A = o.A and
t.B = o.B and
t.POS >= o.POS
left join
Origins o_other
on
t.A = o_other.A and
t.B = o_other.B and
t.POS >= o_other.POS and
o_other.POS > o.POS
where
o_other.POS is null
其中,原始CTE用于查找每个“分区”的第一行。这假设POS
没有间隙-但如果有间隙,则可以使用另一个基于POS
的使用ROW\u NUMBER()
的CTE来代替它
最后一个查询通过查找最近的具有较低的POS
值的行,将每一行连接到“正确的”Origins
行,然后我们将其用作分区的键
结果:
ID POS QTY A B Qty
----------- ----------- ----------- ----------- ----------- -----------
32 1 50 1 2 250
28 2 200 1 2 250
12 3 300 2 2 300
16 4 400 1 2 900
98 5 500 1 2 900
56 6 600 2 2 1300
33 7 700 2 2 1300
(我更改了样本数据以匹配您的预期结果,而不是您问题顶部显示的内容,即条目
3,1
行5
)。Group by(a+B)不起作用,因为组合2+2=1+3=3+1等。如果您知道B的范围(示例B始终<10*a+B)。不起作用,sum(qty)返回sum()对于具有相同A和BAs POS值的所有行都有间隙,您如何使用ROW_NUMBER()而不是POS作为原始CTE?@P.A-只需在顶部添加一个新CTE,其中NewT为(选择*,ROW_NUMBER()在(按POS排序)上作为@t的NewPOS)然后在查询中当前存在@t
和POS
的任何位置使用NewT
和NewPOS
。谢谢,在使用此新CTE时,使用带有行号()的临时表完成了此操作。
ID POS QTY A B Qty
----------- ----------- ----------- ----------- ----------- -----------
32 1 50 1 2 250
28 2 200 1 2 250
12 3 300 2 2 300
16 4 400 1 2 900
98 5 500 1 2 900
56 6 600 2 2 1300
33 7 700 2 2 1300