Oracle SQL - 查找自动增量列的源 ID

时间:2021-06-04 13:10:58

标签: sql oracle group-by subquery oracle-sqldeveloper

我的 ERP 数据库中有一个表格,其中包含有关某些事件的数据。它有开始日期、结束日期和一列显示事件是否是前一个事件的延续(sequential_id 引用 unique_id)。举个例子:

<头>
unique_id 开始日期 结束日期 sequential_id
001 2021-01-01 2021-01-15
002 2021-02-01 2021-02-16 001
003 2021-03-01 2021-03-17 002
004 2021-03-10 2021-03-11
005 2021-03-19

在上面的示例中,第 001、002 和 003 行都是同一事件的一部分,而 004/005 是唯一事件,没有序列。如何以输出如下所示的方式对数据进行分组:

<头>
origin_id 开始日期 结束日期
001 2021-01-01 2021-03-17
004 2021-03-10 2021-03-11
005 2021-03-19

我尝试过使用 group by,但由于sequential_id 是自动增量的,它没有用。

提前致谢。

3 个答案:

答案 0 :(得分:4)

您可以使用现代 match_recognize,这是此类任务的最佳解决方案:

Pattern Recognition With MATCH_RECOGNIZE

DBFiddle

select *
from t
match_recognize(
  measures 
     first(unique_id) start_unique_id,
     first(start_date) start_date,
     last(end_date) end_date
  pattern (strt nxt*)
  define nxt as sequential_id=prev(unique_id)
);

答案 1 :(得分:2)

您可以为此使用分层查询:

<块引用>
with a (unique_id, start_date, end_date, sequential_id) as (
  select '001', date '2021-01-01', date '2021-01-15', null  from dual union all
  select '002', date '2021-02-01', date '2021-02-16', '001' from dual union all
  select '003', date '2021-03-01', date '2021-03-17', '002' from dual union all
  select '004', date '2021-03-10', date '2021-03-11',  null from dual union all
  select '005', date '2021-03-19', null, null               from dual
)
, b as (
  select
    connect_by_root(unique_id) as unique_id
    , connect_by_root(start_date) as start_date
    , end_date
    , connect_by_isleaf as l
  from a
  start with sequential_id is null
  connect by prior unique_id = sequential_id
)
select
  unique_id
  , start_date
  , end_date
from b
where l = 1
order by 1 asc
UNIQUE_ID | START_DATE | END_DATE 
:-------- | :--------- | :--------
001       | 01-JAN-21  | 17-MAR-21
004       | 10-MAR-21  | 11-MAR-21
005       | 19-MAR-21  | null     

db<>fiddle here

答案 2 :(得分:1)

这是一个图遍历问题,因此您可以使用递归 CTE:

with cte (unique_id, start_date, end_date, start_unique_id) as (
      select unique_id, start_date, end_date, unique_id
      from t
      where not exists (select 1 from t t2 where t.sequential_id = t2.unique_id)
      union all
      select t.unique_id, t.start_date, t.end_date, cte.start_unique_id
      from cte join
           t
           on cte.unique_id = t.sequential_id
     )
select start_unique_id, min(start_date), max(end_date)
from cte
group by start_Unique_id;

Here 是一个 db<>fiddle。