聚合序列中的数字

Aggregate numbers that are in sequence

我有一个 table part_tabserial_no:

PART_NO     SERIAL_NO
   A            1
   A            2
   A            3
   A            5
   A            7
   A            8
   A            9
   A            10

我想按顺序将 serial_no 个值聚合在一行中:

PART_NO     SERIAL_NO
   A            1-3
   A            5
   A            7-10

分组依据 part_no。因此,对于第 "A" 号零件,我想 select 在一列中 serial_no 的值为“1-3”、“5”、“7-10”。所选列的范围应从最小值到最大值并按升序排列。

可以 在没有 pl/sql 的情况下使用一些常见的 table 表达式(with 子句)进行查询。它看起来像这样:

with add_break as (
    select part_no, 
           serial_no,
           serial_no-1-lag(serial_no,1,0) over (partition by part_no order by serial_no) brk
    from part_tab
),
add_group as (
    select add_break.*, 
           sum(brk) over (partition by part_no order by serial_no) as grp
    from   add_break
)
select part_no,
       case when min(serial_no) = max(serial_no) then to_char(min(serial_no))
            else to_char(min(serial_no)) || '-' || to_char(max(serial_no))
       end range
from   add_group
group by part_no, grp
order by 1, 2

示例数据的输出:

part_no | range
--------+------
   A    | 1-3
   A    | 5
   A    | 7-10

这是一个间隙和孤岛问题,您可以通过对行编号并从序列号中减去这些数字来解决。这为您提供了所需的组。

select
  part_no,
  case when min(serial_no) = max(serial_no)
    then to_char(min(serial_no))
    else min(serial_no) || '-' || max(serial_no)
  end as serial_nos
from
(
  select
    part_no,
    serial_no,
    serial_no - row_number() over (partition by part_no order by serial_no) as grp
  from mytable
)
group by part_no, grp
order by part_no, min(serial_no);