繁体   English   中英

在DB2中对连续行进行分组

[英]Grouping Consecutive Rows in DB2

我在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。

我宁愿使用查询而不是存储过程来执行此操作。

除非我错过我的猜测,否则可以使用双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小提琴示例
(感谢Brian的初步提琴设置)

...产生预期的结果。 请注意,必须使用MIN(id)才能确保一致的排序顺序groupId并不是唯一的,因此,某些ONETWO行可能最终会翻转。

附带说明一下,我不喜欢在id列上排序,因为这样的id 唯一真正有用的就是唯一性 在行可能被更新或以其他方式重新解释的情况下尤其如此-您是否有类似insertedAt时间戳之类的东西可用于排序?

认为我明白了:

小提琴:

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子句和window函数,因此它应该可以工作,即使有任何微小的修改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM