DECLARE @TotalMaxQty int
SET @TotalMaxQty = 1000
SELECT
PKId
,Qty
FROM dbo.Sales
PKId Qty
____ _____
1 100
2 200
3 750
4 200
...
由于SUM(Qty) <= @TotalMaxQty
,我必须获得1,2,3条记录(记录3应部分包括在内,数量= 700)。
谢谢。
答案 0 :(得分:1)
这些方面的东西应该可以解决问题。 (注意:拥有TOP
和子查询的原因是一旦达到目标就停止三角形连接计算。
SELECT *
FROM Sales
WHERE PKId < = ( SELECT TOP 1
S1.PKId
FROM Sales S1
LEFT JOIN Sales S2 ON S1.PKId >= S2.PKId
GROUP BY S1.PKId
HAVING SUM(S2.Qty) >= @TotalMaxQty
ORDER BY PKId
)
答案 1 :(得分:1)
您可以使用递归CTE计算运行总和。
declare @Sales table (PKId int, Qty int)
insert into @Sales values
(1, 100),
(2, 200),
(3, 750),
(4, 200)
declare @TotalMaxQty int = 1000
;with OrderedSales as
(
select PKId,
Qty,
row_number() over(order by PKId) as rn
from @Sales
--where "some where clause against Sales"
),
RunningSum as
(
select OS.PKId,
case when OS.Qty < @TotalMaxQty then OS.Qty
else @TotalMaxQty
end as Qty,
@TotalMaxQty - OS.Qty as Rest,
OS.rn
from OrderedSales OS
where rn = 1
union all
select OS.PKId,
case when OS.Qty < RS.Rest then OS.Qty
else RS.Rest
end as Qty,
RS.Rest - OS.Qty,
OS.rn
from OrderedSales as OS
inner join RunningSum as RS
on OS.rn = RS.rn + 1
where RS.Rest > 0
)
select PKId,
Qty
from RunningSum
option (maxrecursion 0)
编辑:将订购的销售额存储在以rn
为主键的表变量中的版本。我的测试表明性能大大提高。
declare @Sales table (PKId int, Qty int)
insert into @Sales values
(1, 100),
(2, 200),
(3, 750),
(4, 200)
declare @TotalMaxQty int = 1000
declare @OrderedSales table
(
rn int primary key,
PKId int,
Qty int
)
insert into @OrderedSales
select row_number() over(order by PKId),
PKId,
Qty
from @Sales
--where "some where clause against Sales"
;with RunningSum as
(
select OS.PKId,
case when OS.Qty < @TotalMaxQty then OS.Qty
else @TotalMaxQty
end as Qty,
@TotalMaxQty - OS.Qty as Rest,
OS.rn
from @OrderedSales OS
where rn = 1
union all
select OS.PKId,
case when OS.Qty < RS.Rest then OS.Qty
else RS.Rest
end as Qty,
RS.Rest - OS.Qty,
OS.rn
from @OrderedSales as OS
inner join RunningSum as RS
on OS.rn = RS.rn + 1
where RS.Rest > 0
)
select PKId,
Qty
from RunningSum
option (maxrecursion 0)
答案 2 :(得分:1)
记录3应部分包含在Qty = 700
中
这部分在sql中是个坏主意,原因有两个:在客户端代码中执行此操作会更有效率,并且为了做到这一点,您还需要在某处更新或插入记录以了解如何剩余的大部分数量(意味着你需要另一个困难的查询)。
但如果你坚持:
SELECT s.PKId, CASE WHEN PriorTotal + Qty > @TotalMaxQty THEN @TotalMaxQty - PriorTotal ELSE Qty END As Qty
FROM SALES s
INNER JOIN (
SELECT s1.PKId, Sum(s2.Qty) As PriorTotal
FROM SALES s1
LEFT JOIN SALES s2 ON s2.PKId < s1.PKId
GROUP BY s1.PKId
) q ON q.PKId = s.PKId
WHERE q.PriorTotal < @TotalMaxQty
ORDER BY s.Qty