Oracle SQL - 查找自增列的原始 ID
Oracle SQL - Find origin ID of autoincrement column
我的 ERP 数据库中有一个 table,其中包含有关某些事件的数据。它有开始日期、结束日期和一列显示事件是否是前一个事件的延续(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,但由于 sequential_id 是自动递增的,所以没用。
提前致谢。
您可以为此使用分层查询:
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
这是一个图遍历问题,因此您可以使用递归 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.
您可以使用现代 match_recognize
,这是此类任务的最佳解决方案:
Pattern Recognition With MATCH_RECOGNIZE
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)
);
我的 ERP 数据库中有一个 table,其中包含有关某些事件的数据。它有开始日期、结束日期和一列显示事件是否是前一个事件的延续(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,但由于 sequential_id 是自动递增的,所以没用。
提前致谢。
您可以为此使用分层查询:
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
这是一个图遍历问题,因此您可以使用递归 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.
您可以使用现代 match_recognize
,这是此类任务的最佳解决方案:
Pattern Recognition With MATCH_RECOGNIZE
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)
);