T-SQL在没有游标的行之间分配值

mal*_*pka 5 t-sql sql-server window-functions sql-server-2014

我在SQL Server 2014上有一个简单的实时案例.我有一个包含订单及其数量的表格:

declare @qty_to_distribute int = 50

create table orders (id int, priority int, qty int)

insert into orders (id, priority, qty) values
(1, 1, 10),
(2, 2, 30),
(3, 3, 20),
(4, 4, 5)
Run Code Online (Sandbox Code Playgroud)

我有一个值,例如50,我必须根据他们的优先顺序通过订单在订单之间分配

  • 如果剩余的金额大于当前订单的数量,则订单将被实现,并且@qty_to_distribute减少订单的数量,
  • 如果不是 - 订单被取消.

查看样本数据 - 将实现订单1,2和4,并取消#3.

是否有一个简单,有效和非游标的解决方案,最好是基于窗口函数?

这看起来很有希望,但无法弄清楚在哪里放置条件:

select id,
sum(qty) OVER (ORDER BY priority asc ROWS UNBOUNDED PRECEDING) as qtysum
from orders

id  qtysum
1   10
2   40
3   60      *
4   65      *
Run Code Online (Sandbox Code Playgroud)

http://sqlfiddle.com/#!6/05fa2/2/0

Gio*_*uri 6

试试这个:

create table o (id int, priority int, qty int)

insert into o (id, priority, qty) values
(1, 1, 10),
(2, 2, 30),
(3, 3, 20),
(4, 4, 5),
(5, 5, 1),
(6, 6, 10)

with cte1 as(select *, row_number() over(order by priority) as rn from o),
cte2 as(
  select top 1 id, priority, qty, rn,
  case when qty > 50 then 1 else 0 end as ToBeCanceled
  from cte1 order by rn
    Union all
  select cte1.id, cte1.priority, case when cte2.qty + cte1.qty > 50 then cte2.qty
  else cte2.qty + cte1.qty end as qty,
  cte1.rn,
  case when cte2.qty + cte1.qty > 50 then 1 else 0 end as ToBeCanceled 
  from cte1
  join cte2 on cte1.rn = cte2.rn + 1)
select id, priority, ToBeCanceled from cte2
option(maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)

输出:

id  ToBeCanceled
1   0
2   0
3   1
4   0
5   0
6   1
Run Code Online (Sandbox Code Playgroud)

小提琴http://sqlfiddle.com/#!6/87ac9/19