I have a data set with overlapping dates in a slowly changing dimension table. I am trying to come up with a query to find out the persons with overlapping date ranges based on few conditions.
for example
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
I want to find the person_ids with overlapping date ranges only when atleast one of the relationship_id is -1. for example, BOB is both associate and teacher for overlapping periods. its ok to have 2 roles for a person. However, i want to find out all persons with overlapping dates which involves "None" relationship and some other role. Example: steve.
Could you please give me some suggestions as to how to come up with a query
Oracle Setup:
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;
Query:
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
)
Output:
| PERSON_ID | | :-------- | | STEVE |
db<>fiddle here