【问题标题】:Oracle SQL - Find origin ID of autoincrement columnOracle SQL - 查找自动增量列的原始 ID
【发布时间】:2021-08-22 13:02:36
【问题描述】:

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

unique_id start_date end_date 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 start_date end_date
001 2021-01-01 2021-03-17
004 2021-03-10 2021-03-11
005 2021-03-19

我尝试过使用 group by,但由于 sequence_id 是自动递增的,它不起作用。

提前致谢。

【问题讨论】:

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


    【解决方案1】:

    您可以使用现代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)
    );
    

    【讨论】:

      【解决方案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 |结束日期 :-------- | :--------- | :-------- 001 | 21 年 1 月 1 日 | 21 年 3 月 17 日 004 | 21 年 3 月 10 日 | 21 年 3 月 11 日 005 | 21 年 3 月 19 日 |

      db小提琴here

      【讨论】:

        【解决方案3】:

        这是一个图行走问题,因此您可以使用递归 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 是一个 dbfiddle。

        【讨论】:

          猜你喜欢
          • 2014-06-28
          • 1970-01-01
          • 2015-12-30
          • 2012-12-23
          • 2022-11-30
          • 1970-01-01
          • 2011-10-22
          • 1970-01-01
          • 2012-04-01
          相关资源
          最近更新 更多