sql - 如何使用 SQL 忽略组中的相同连续记录

标签 sql oracle listagg

我有以下数据:

ItemID | ProdID | ItemTypeID
=======+========+===========
1001   | 100    | A
1002   | 100    | B
1003   | 100    | A
1004   | 100    | B
1005   | 100    | B  <- successive itemtype (should be excluded)
1006   | 100    | C
1007   | 200    | C
1008   | 200    | A

我想在每个组中列出 ItemTypeID (LISTAGG),但没有相同的连续 ID。所以我的结果应该是这样的:

ProdID | ItemTypes
=======+==========
100    | A,B,A,B,C <- not A,B,A,B,B,C (successive B)
200    | C,A

最佳答案

这很棘手。 Listagg() 甚至不允许 distinct,所以所有的工作都需要在子查询中完成。

您可以使用行号差异方法来识别连续的 ItemTypeId。然后,一旦确定了组,您就可以按组聚合,然后执行 listagg():

select ProdId,
       listagg(ItemId, ',') within group (order by seqnum) as items
from (select ProdId, ItemId, count(*) as NumItems,
             row_number() over (partition by ProdId order by min(ItemId)) as seqnum
      from (select t.*,
                   (row_number() over (partition by ProdId order by ItemId) -
                    row_number() over (partition by ProdId, ItemTypeId order by ItemId)
                   ) as grp
            from t
           ) t
      group by ProdId, ItemTypeId, grp
     ) t
group by ProdId;

编辑:

解决此问题的另一种方法是使用 lag() 来查找新组的开始位置。前面的方法允许您获取计数。这种方法可能更容易理解:

select ProdId,
       listagg(ItemId, ',') within group (order by ItemId) as items
from (select t.*
      from (select t.*,
                   lag(ItemTypeId) over (partition by ProdId order by ItemId) as prev_ItemTypeId
            from t
           ) t
      where prev_ItemTypeId is null or prev_ItemTypeId <> ItemTypeId
     ) t
group by ProdId;

关于sql - 如何使用 SQL 忽略组中的相同连续记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35677114/

相关文章:

mysql - SQL varchar 列长度的最佳实践

mysql - mysql中有没有类似操作符重载的机制?

sql - 在 Oracle DB 中使用 LISTAGG 时,如何从字符串中删除 CHR(0)?

sql - Listagg 两列 + 当共享相同值时将它们分组

mysql - 匹配mysql数据库中的关键词

sql - 如何在 SQL 查询中返回计数而不计数?

oracle - 安全的 INTERVAL 算术

sql - 比较忽略字符串的SQL重音(ORACLE)

sql - 有没有一种方法可以不使用 FOR 循环来创建虚拟记录?