我在DB2中有一个表如下所示: -
ID DESCRIPTION TYPE AMOUNT
-- ----------- ---- ------
1 Item 1 ONE 100
2 Item 2 ONE 50
3 Item 3 TWO 100
4 Item 4 TWO 50
5 Item 5 ONE 100
6 Item 6 TWO 50
7 Item 7 ONE 100
8 Item 8 TWO 50
9 Item 9 TWO 100
10 Item 10 ONE 50
我想将具有相同类型的连续行分组,如下所示: -
TYPE AMOUNT
---- ------
ONE 150 -- (ID 1,2)
TWO 150 -- (ID 3,4)
ONE 100 -- (ID 5)
TWO 50 -- (ID 6)
ONE 100 -- (ID 7)
TWO 150 -- (ID 8,9)
ONE 50 -- (ID 10)
请注意,最后一列只是表示汇总中的哪些ID。
我宁愿使用查询而不是存储过程来执行此操作。
答案 0 :(得分:2)
除非我错过了我的猜测,否则可以通过双重ROW_NUMBER()
常量表达式轻松完成:
SELECT type, SUM(amount) AS amount
FROM (SELECT type, amount, id,
ROW_NUMBER() OVER(ORDER BY id)
- ROW_NUMBER() OVER(PARTITION BY type ORDER BY id) AS groupId
FROM tbl) grouped
GROUP BY groupId, type
ORDER BY groupId, MIN(id)
SQL Fiddle Example
(感谢Brian为最初的小提琴设置)
......产生了预期的结果。请注意,MIN(id)
是确保一致排序顺序所必需的 - groupId
并非普遍唯一,因此否则某些ONE
或TWO
行最终会被翻转。
作为旁注,我不喜欢在id
列上进行排序,因为唯一真正有用的内容是 uniqueness 。在行可能被更新或以其他方式重新解释的情况下尤其如此 - 您是否有类似insertedAt
时间戳的内容可用于订购?
答案 1 :(得分:0)
想想我明白了:
with sub1 as
(select x.*,
case when chk is not null
then row_number() over(order by id)
else null
end as rn
from (select id,
description,
type,
amount,
case when lag(type, 1) over(order by id) <> type
then 'X'
else null
end as chk
from tbl
order by id) x)
select min(type),
sum(amount) as amount,
listagg(id, ', ') within group(order by id) as ids
from (select z.id, z.description, z.type, z.amount, y.rn
from sub1 z
cross join sub1 y
where z.rn is null
and y.rn = (select max(x.rn)
from sub1 x
where x.id < z.id
and x.rn is not null)
union all
select id, description, type, amount, rn
from sub1
where rn is not null
union all
select id, description, type, amount, 1
from sub1
where id < (select min(id) from sub1 where rn is not null)
order by id) x
group by rn
order by rn
我在Oracle中对它进行了测试,但它只依赖于我认为DB2具有的with子句和窗口函数,所以它应该可以工作,如果有任何修改的话。