SQL 服务器:使用带有序集的 Windows 函数

SQL Server: Use of Windows Function with ordered set

使用此示例数据集:

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

如何按组获取 SUM(QTY)。组基于不同的 (A 和 B) 按 POS 排序!!!

作为:

ID POS QTY A B SUM(QTY)
32 1 50 1 2 250 第一组
28 2 200 1 2 250 第 1 组
12 3 300 2 2 300 第 2 组
16 4 400 1 2 900 第 3 组而非 1
98 5 500 1 2 900 第 3 组而非第 1 组
56 6 600 2 2 1300 第 4 组而非第 2 组
33 7 700 2 2 1300 第 4 组而非第 2 组

我尝试过使用 PARTITION BY 的不同解决方案,但总是得到具有相同 A 和 B 总和的组。

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

其中 Origins CTE 用于查找每个 "partition" 的第一行。这假设 POS 没有间隙 - 但如果有,则可以使用基于 POS 使用 ROW_NUMBER() 的另一个 CTE 代替它。

最后的查询然后通过找到最近的具有较低 POS 值的行将每一行连接到 "correct" 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)。