示例数据:
create table #temp (id int, qty int, checkvalue int)
insert into #temp values (1,1,3)
insert into #temp values (2,2,3)
insert into #temp values (3,1,3)
insert into #temp values (4,1,3)
根据上面的数据,我想显示sum(qty) = checkvalue
从上到下的确切行数。请注意,所有记录的checkvalue始终相同。关于上面的示例数据,所需的输出是:
Id Qty checkValue
1 1 3
2 2 3
因为1 + 2 = 3并且不再需要显示数据。如果checkvalue为4,我们将显示第三条记录:Id:3 Qty:1 checkValue:4
。
这是我正在处理此问题的代码。代码运行得很好。
declare @checkValue int = (select top 1 checkvalue from #temp);
declare @counter int = 0, @sumValue int = 0;
while @sumValue < @checkValue
begin
set @counter = @counter + 1;
set @sumValue = @sumValue + (
select t.qty from
(
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY id ASC) AS rownumber,
id,qty,checkvalue
FROM #temp
) AS foo
WHERE rownumber = @counter
) t
)
end
declare @sql nvarchar(255) = 'select top '+cast(@counter as varchar(5))+' * from #temp'
EXECUTE sp_executesql @sql, N'@counter int', @counter = @counter;
但是,我不确定这是否是处理它的最佳方法,并想知道是否有更好的方法。这里有很多专业人士,我想听听他们对我的方法的看法以及我们如何改进它。任何建议将不胜感激!
答案 0 :(得分:1)
对于SQL Server 2012及更高版本,您可以使用C16
子句中的ROWS BETWEEN
和使用CTE轻松实现此目的:
OVER
答案 1 :(得分:1)
试试这个:
select id, qty, checkvalue from (
select t1.*,
sum(t1.qty) over (partition by t2.id) [sum]
from #temp [t1] join #temp [t2] on t1.id <= t2.id
) a where checkvalue = [sum]
智能自我加入就是您所需要的:)
答案 2 :(得分:0)
一个基本的改进是尝试&amp;减少号码。迭代。你递增1,但如果你重新利用二进制搜索背后的逻辑,你就会得到一些接近这个的东西:
19
答案 3 :(得分:0)
对于SQL 2008,您可以使用recursive cte
。第一次合并会导致Top 1 with ties
限制结果。删除它以查看所有组合
with cte as (
select
*, rn = row_number() over (order by id)
from
#temp
)
, rcte as (
select
i = id, id, qty, sumV = qty, checkvalue, rn
from
cte
union all
select
a.id, b.id, b.qty, a.sumV + b.qty, a.checkvalue, b.rn
from
rcte a
join cte b on a.rn + 1 = b.rn
where
a.sumV < b.checkvalue
)
select
top 1 with ties id, qty, checkvalue
from (
select
*, needed = max(case when sumV = checkvalue then 1 else 0 end) over (partition by i)
from
rcte
) t
where
needed = 1
order by dense_rank() over (order by i)