我需要将数据汇总到包含数字数据的一列。
我有以下数据:
ID | Amount
---+-------
1 | 44
2 | 15
3 | 16
4 | 8
5 | 16
结果,我期待的是:
ID | Amount
---+-------
1 | 44
2 | 31
4 | 24
查询应将ID
列按Amount
列排序的数据按最大金额32的部分进行分组。如果金额大于32,则应将其显示为一个'组&# 39 ;.结果应包含Min(ID)
和SUM(Amount)
,当组合多个记录时,该结果不能超过32。
答案 0 :(得分:0)
我知道如何实现这一目标的唯一方法是使用迭代(尽管在你的情况下,如果你有足够的单个值超过32,那么你可能能够使用更有效的方法)。
SQL Server查询中的迭代由递归CTE处理(一旦你放弃了游标):
with v as (
select *
from (values (1, 44), (2, 15), (3, 16), (4, 8), (5, 16) ) v(id, amount)
),
t as (
select v.*, row_number() over (order by id) as seqnum
),
cte as (
select seqnum, id, amount, id as grp
from t
where seqnum = 1
union all
select t.seqnum, t.id,
(case when t.amount + cte.amount > 32 then t.amount else t.amount + cte.amount end) as amount,
(case when t.amount + cte.amount > 32 then t.id else cte.grp end) as grp
from cte join
t
on cte.seqnum = t.seqnum + 1
)
select grp, max(amount)
from cte
group by grp;
我应该注意在外部查询中使用max(amount)
假设值永远不会为负。稍作修改即可处理这种情况。
此外,使用t
的中间结果对于您提供的数据并不是绝对必要的。它确保join
中使用的列实际上没有间隙。
答案 1 :(得分:0)
您可以尝试使用最初分配的rownumbers这个版本,并在递归cte中将每一行连接到前一行。如果运行总和> 32一个新组开始。
with rownums as (select t.*,row_number() over(order by id) as rnum from t)
,cte(rnum,id,amount,runningsum,grp) as (select rnum,id,amount,amount,1 from rownums where rnum=1
union all
select t.rnum,t.id,t.amount
,case when c.runningsum+t.amount > 32 then t.amount else c.runningsum+t.amount end
,case when c.runningsum+t.amount > 32 then t.id else c.grp end
from cte c
join rownums t on t.rnum=c.rnum+1
)
select grp as id,max(runningsum) as amount
from cte
group by grp