oracle 查询以识别一些基于重叠日期期间的条件
oracle query to identify some condition based overlapping date periods
我有一个数据集,其日期在一个缓慢变化的维度 table 中重叠。我正在尝试提出一个查询,以根据少数条件找出具有重叠日期范围的人。
例如
PERSON_ID,RELATION_ID,RELATION_NAME,START_DT, END_DT, ACTIVE_IND,LATEST_ROW
STEVE -1 NONE 7/26/2018 10/24/2018 Y N
STEVE 111 STUDENT 8/8/2018 10/22/2018 Y N
STEVE 111 STUDENT 10/23/2018 12/31/4712 Y Y
STEVE -1 NONE 10/25/2018 2/7/2019 Y N
STEVE 222 Manager 8/9/2018 12/31/4712 Y Y
BOB 333 ASSOCIATE 8/9/2018 12/31/4712 Y Y
BOB 666 TEACHER 8/10/2018 12/31/4712 Y Y
Dave 555 Director 8/9/2018 12/31/4712 Y Y
我想找到具有重叠日期范围的 person_ids,仅当 relationship_id 中至少有一个为 -1 时。例如,BOB 在重叠时期既是同事又是老师。一个人有两个角色是可以的。但是,我想找出所有日期重叠的人,这些人涉及 "None" 关系和其他一些角色。例子:史蒂夫。
你能给我一些关于如何提出查询的建议吗
Oracle 设置:
CREATE TABLE table_name ( PERSON_ID, RELATION_ID, RELATION_NAME, START_DT, END_DT, ACTIVE_IND,LATEST_ROW ) AS
SELECT 'STEVE', -1, 'NONE', DATE '2018-07-26', DATE '2018-10-24', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 111, 'STUDENT', DATE '2018-08-08', DATE '2018-10-22', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 111, 'STUDENT', DATE '2018-10-23', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'STEVE', -1, 'NONE', DATE '2018-10-25', DATE '2019-02-07', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 222, 'Manager', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'BOB', 333, 'ASSOCIATE', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'BOB', 666, 'TEACHER', DATE '2018-08-10', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'Dave', 555, 'Director', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL;
查询:
SELECT DISTINCT
PERSON_ID
FROM table_name t
WHERE RELATION_ID = -1
AND EXISTS (
SELECT 1
FROM table_name o
WHERE t.person_id = o.person_id
AND t.end_dt > o.start_dt
AND t.start_dt < o.end_dt
AND o.relation_id <> -1
)
输出:
| PERSON_ID |
| :-------- |
| STEVE |
db<>fiddle here
用上面的模式识别拍了一张照片,它显示了所有相互重叠的行。在这种情况下,一行在 RELATION_IDs = -1 中重叠了两次,因此它在两种重叠情况下都显示同一行,并且查询将其标记为 overlap_num 1 和 2.
with t (PERSON_ID,RELATION_ID,RELATION_NAME,START_DT, END_DT, ACTIVE_IND,LATEST_ROW) as (
select 'STEVE', -1, 'NONE', to_date('7/26/2018', 'MM/DD/YYYY'), to_date('10/24/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE', 111, 'STUDENT', to_date('8/8/2018', 'MM/DD/YYYY'), to_date('10/22/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE', 111, 'STUDENT', to_date('10/23/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'STEVE', -1, 'NONE', to_date('10/25/2018', 'MM/DD/YYYY'), to_date('2/7/2019', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE', 222, 'Manager', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'BOB', 333, 'ASSOCIATE', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'BOB', 666, 'TEACHER', to_date('8/10/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'Dave', 555, 'Director', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual)
select person_id, var_match, overlap_num, relation_id, start_dt, end_dt, start_dt_overlap, end_dt_overlap
from t
match_recognize (
partition by person_id order by start_dt
measures
classifier() as var_match,
match_number() as overlap_num,
last(start_dt) as start_dt_overlap,
first(end_dt) as end_dt_overlap
all rows per match
after match skip to last ovlap
pattern (strt ovlap+)
define ovlap as (strt.relation_id = -1 and start_dt <= strt.end_dt)
or (ovlap.relation_id = -1 and strt.start_dt <= prev(strt.end_dt))
)
order by person_id, overlap_num, start_dt;
示例执行:
FSITJA@db01 2019-07-11 14:55:17> with t (PERSON_ID,RELATION_ID,RELATION_NAME,START_DT, END_DT, ACTIVE_IND,LATEST_ROW) as (
2 select 'STEVE', -1, 'NONE', to_date('7/26/2018', 'MM/DD/YYYY'), to_date('10/24/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
3 select 'STEVE', 111, 'STUDENT', to_date('8/8/2018', 'MM/DD/YYYY'), to_date('10/22/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
4 select 'STEVE', 111, 'STUDENT', to_date('10/23/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
5 select 'STEVE', -1, 'NONE', to_date('10/25/2018', 'MM/DD/YYYY'), to_date('2/7/2019', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
6 select 'STEVE', 222, 'Manager', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
7 select 'BOB', 333, 'ASSOCIATE', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
8 select 'BOB', 666, 'TEACHER', to_date('8/10/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
9 select 'Dave', 555, 'Director', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual)
10 select person_id, var_match, overlap_num, relation_id, start_dt, end_dt, start_dt_overlap, end_dt_overlap
11 from t
12 match_recognize (
13 partition by person_id order by start_dt
14 measures
15 classifier() as var_match,
16 match_number() as overlap_num,
17 last(start_dt) as start_dt_overlap,
18 first(end_dt) as end_dt_overlap
19 all rows per match
20 after match skip to last ovlap
21 pattern (strt ovlap+)
22 define ovlap as (strt.relation_id = -1 and start_dt <= strt.end_dt)
23 or (ovlap.relation_id = -1 and strt.start_dt <= prev(strt.end_dt))
24 )
25 order by person_id, overlap_num, start_dt;
PERSO VAR_MATCH OVERLAP_NUM RELATION_ID START_DT END_DT START_DT_OVERLAP END_DT_OVERLAP
----- ---------- ----------- ----------- ------------------- ------------------- ------------------- -------------------
STEVE STRT 1 -1 2018-07-26 00:00:00 2018-10-24 00:00:00 2018-07-26 00:00:00 2018-10-24 00:00:00
STEVE OVLAP 1 111 2018-08-08 00:00:00 2018-10-22 00:00:00 2018-08-08 00:00:00 2018-10-24 00:00:00
STEVE OVLAP 1 222 2018-08-09 00:00:00 4712-12-31 00:00:00 2018-08-09 00:00:00 2018-10-24 00:00:00
STEVE OVLAP 1 111 2018-10-23 00:00:00 4712-12-31 00:00:00 2018-10-23 00:00:00 2018-10-24 00:00:00
STEVE STRT 2 111 2018-10-23 00:00:00 4712-12-31 00:00:00 2018-10-23 00:00:00 4712-12-31 00:00:00
STEVE OVLAP 2 -1 2018-10-25 00:00:00 2019-02-07 00:00:00 2018-10-25 00:00:00 4712-12-31 00:00:00
6 rows selected.
我有一个数据集,其日期在一个缓慢变化的维度 table 中重叠。我正在尝试提出一个查询,以根据少数条件找出具有重叠日期范围的人。
例如
PERSON_ID,RELATION_ID,RELATION_NAME,START_DT, END_DT, ACTIVE_IND,LATEST_ROW
STEVE -1 NONE 7/26/2018 10/24/2018 Y N
STEVE 111 STUDENT 8/8/2018 10/22/2018 Y N
STEVE 111 STUDENT 10/23/2018 12/31/4712 Y Y
STEVE -1 NONE 10/25/2018 2/7/2019 Y N
STEVE 222 Manager 8/9/2018 12/31/4712 Y Y
BOB 333 ASSOCIATE 8/9/2018 12/31/4712 Y Y
BOB 666 TEACHER 8/10/2018 12/31/4712 Y Y
Dave 555 Director 8/9/2018 12/31/4712 Y Y
我想找到具有重叠日期范围的 person_ids,仅当 relationship_id 中至少有一个为 -1 时。例如,BOB 在重叠时期既是同事又是老师。一个人有两个角色是可以的。但是,我想找出所有日期重叠的人,这些人涉及 "None" 关系和其他一些角色。例子:史蒂夫。
你能给我一些关于如何提出查询的建议吗
Oracle 设置:
CREATE TABLE table_name ( PERSON_ID, RELATION_ID, RELATION_NAME, START_DT, END_DT, ACTIVE_IND,LATEST_ROW ) AS
SELECT 'STEVE', -1, 'NONE', DATE '2018-07-26', DATE '2018-10-24', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 111, 'STUDENT', DATE '2018-08-08', DATE '2018-10-22', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 111, 'STUDENT', DATE '2018-10-23', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'STEVE', -1, 'NONE', DATE '2018-10-25', DATE '2019-02-07', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 222, 'Manager', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'BOB', 333, 'ASSOCIATE', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'BOB', 666, 'TEACHER', DATE '2018-08-10', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'Dave', 555, 'Director', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL;
查询:
SELECT DISTINCT
PERSON_ID
FROM table_name t
WHERE RELATION_ID = -1
AND EXISTS (
SELECT 1
FROM table_name o
WHERE t.person_id = o.person_id
AND t.end_dt > o.start_dt
AND t.start_dt < o.end_dt
AND o.relation_id <> -1
)
输出:
| PERSON_ID | | :-------- | | STEVE |
db<>fiddle here
用上面的模式识别拍了一张照片,它显示了所有相互重叠的行。在这种情况下,一行在 RELATION_IDs = -1 中重叠了两次,因此它在两种重叠情况下都显示同一行,并且查询将其标记为 overlap_num 1 和 2.
with t (PERSON_ID,RELATION_ID,RELATION_NAME,START_DT, END_DT, ACTIVE_IND,LATEST_ROW) as (
select 'STEVE', -1, 'NONE', to_date('7/26/2018', 'MM/DD/YYYY'), to_date('10/24/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE', 111, 'STUDENT', to_date('8/8/2018', 'MM/DD/YYYY'), to_date('10/22/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE', 111, 'STUDENT', to_date('10/23/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'STEVE', -1, 'NONE', to_date('10/25/2018', 'MM/DD/YYYY'), to_date('2/7/2019', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE', 222, 'Manager', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'BOB', 333, 'ASSOCIATE', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'BOB', 666, 'TEACHER', to_date('8/10/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'Dave', 555, 'Director', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual)
select person_id, var_match, overlap_num, relation_id, start_dt, end_dt, start_dt_overlap, end_dt_overlap
from t
match_recognize (
partition by person_id order by start_dt
measures
classifier() as var_match,
match_number() as overlap_num,
last(start_dt) as start_dt_overlap,
first(end_dt) as end_dt_overlap
all rows per match
after match skip to last ovlap
pattern (strt ovlap+)
define ovlap as (strt.relation_id = -1 and start_dt <= strt.end_dt)
or (ovlap.relation_id = -1 and strt.start_dt <= prev(strt.end_dt))
)
order by person_id, overlap_num, start_dt;
示例执行:
FSITJA@db01 2019-07-11 14:55:17> with t (PERSON_ID,RELATION_ID,RELATION_NAME,START_DT, END_DT, ACTIVE_IND,LATEST_ROW) as (
2 select 'STEVE', -1, 'NONE', to_date('7/26/2018', 'MM/DD/YYYY'), to_date('10/24/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
3 select 'STEVE', 111, 'STUDENT', to_date('8/8/2018', 'MM/DD/YYYY'), to_date('10/22/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
4 select 'STEVE', 111, 'STUDENT', to_date('10/23/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
5 select 'STEVE', -1, 'NONE', to_date('10/25/2018', 'MM/DD/YYYY'), to_date('2/7/2019', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
6 select 'STEVE', 222, 'Manager', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
7 select 'BOB', 333, 'ASSOCIATE', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
8 select 'BOB', 666, 'TEACHER', to_date('8/10/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
9 select 'Dave', 555, 'Director', to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual)
10 select person_id, var_match, overlap_num, relation_id, start_dt, end_dt, start_dt_overlap, end_dt_overlap
11 from t
12 match_recognize (
13 partition by person_id order by start_dt
14 measures
15 classifier() as var_match,
16 match_number() as overlap_num,
17 last(start_dt) as start_dt_overlap,
18 first(end_dt) as end_dt_overlap
19 all rows per match
20 after match skip to last ovlap
21 pattern (strt ovlap+)
22 define ovlap as (strt.relation_id = -1 and start_dt <= strt.end_dt)
23 or (ovlap.relation_id = -1 and strt.start_dt <= prev(strt.end_dt))
24 )
25 order by person_id, overlap_num, start_dt;
PERSO VAR_MATCH OVERLAP_NUM RELATION_ID START_DT END_DT START_DT_OVERLAP END_DT_OVERLAP
----- ---------- ----------- ----------- ------------------- ------------------- ------------------- -------------------
STEVE STRT 1 -1 2018-07-26 00:00:00 2018-10-24 00:00:00 2018-07-26 00:00:00 2018-10-24 00:00:00
STEVE OVLAP 1 111 2018-08-08 00:00:00 2018-10-22 00:00:00 2018-08-08 00:00:00 2018-10-24 00:00:00
STEVE OVLAP 1 222 2018-08-09 00:00:00 4712-12-31 00:00:00 2018-08-09 00:00:00 2018-10-24 00:00:00
STEVE OVLAP 1 111 2018-10-23 00:00:00 4712-12-31 00:00:00 2018-10-23 00:00:00 2018-10-24 00:00:00
STEVE STRT 2 111 2018-10-23 00:00:00 4712-12-31 00:00:00 2018-10-23 00:00:00 4712-12-31 00:00:00
STEVE OVLAP 2 -1 2018-10-25 00:00:00 2019-02-07 00:00:00 2018-10-25 00:00:00 4712-12-31 00:00:00
6 rows selected.