Question: Oracle Date ranges that are present in parent rows but not in child rows

Dates ranges that are found in rule1 but 'not in' rule2 E.g.,




item_no
item_type
active_from
active_to
ruleid




10001
SAR
2022-01-01
2023-05-31
rule1


10001
SAR
2023-07-01
2099-12-31
rule1


10001
SAR
2023-01-01
9999-12-31
rule2


10001
SAR
2020-12-01
2021-12-31
rule2




In this case output will be the date ranges which are in rule1 but not in rule2 is.
10001 SAR 2022-01-01 2022-12-31 

I have used connect by level which is taking more time to generate dates and compare them.. as date end is 9999-12-31.


Answer:
Adapting my answer to your previous question, from Oracle 12, you can UNPIVOT the dates and then use analytic functions and MATCH_RECOGNIZE to process the result set row-by-row to find the consecutive rows where rule1 is active and rule2 is inactive:
SELECT item_no,
       item_type,
       active_from
       + CASE
         WHEN prev_rule2 > 0
         THEN INTERVAL '1' SECOND
         ELSE INTERVAL '0' SECOND
         END AS active_from,
       active_to
       - CASE
         WHEN next_rule2 > 0
         THEN INTERVAL '1' SECOND
         ELSE INTERVAL '0' SECOND
         END AS active_to
FROM   (
  SELECT item_no,
         item_type,
         rule_id,
         dt,
         COALESCE(
           SUM(CASE rule_id WHEN 'rule1' THEN active END) OVER (
             PARTITION BY item_no, item_type ORDER BY dt, ACTIVE DESC
           ),
           0
         ) AS rule1,
         COALESCE(
           SUM(CASE rule_id WHEN 'rule2' THEN active END) OVER (
             PARTITION BY item_no, item_type ORDER BY dt, ACTIVE DESC
           ),
           0
         ) AS rule2
  FROM   table_name
         UNPIVOT (
           dt FOR active IN ( active_from AS 1, active_to AS -1 )
         )
)
MATCH_RECOGNIZE(
  PARTITION BY item_no, item_type
  ORDER BY dt, rule1 DESC, rule2 DESC
  MEASURES
    FIRST(dt) AS active_from,
    PREV(rule1) AS prev_rule1,
    PREV(rule2) AS prev_rule2,
    NEXT(dt) AS active_to,
    NEXT(rule1) AS next_rule1,
    NEXT(rule2) AS next_rule2
  PATTERN ( active_rules+ )
  DEFINE active_rules AS rule1 > 0 AND rule2 = 0
)

Which, for the sample data from your previous question:
CREATE TABLE table_name (Item_no, item_type, active_from, active_to, rule_id) AS
SELECT 10001, 'SAR', DATE '2020-01-01', DATE '2023-01-01', 'rule1' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2024-01-01', DATE '9999-12-31', 'rule1' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2020-05-01', DATE '2021-06-01', 'rule2' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2021-01-01', DATE '2021-02-01', 'rule2' FROM DUAL;

Outputs:




ITEM_NO
ITEM_TYPE
ACTIVE_FROM
ACTIVE_TO




10001
SAR
2020-01-01 00:00:00
2020-04-30 23:59:59


10001
SAR
2021-06-01 00:00:01
2023-01-01 00:00:00


10001
SAR
2024-01-01 00:00:00
9999-12-31 00:00:00




And, for the sample data in this question:
CREATE TABLE table_name (Item_no, item_type, active_from, active_to, rule_id) AS
SELECT 10001, 'SAR', DATE '2022-01-01', DATE '2023-05-31', 'rule1' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2023-07-01', DATE '2099-12-31', 'rule1' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2023-01-01', DATE '9999-12-31', 'rule2' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2020-12-01', DATE '2021-12-31', 'rule2' FROM DUAL;

Outputs:




ITEM_NO
ITEM_TYPE
ACTIVE_FROM
ACTIVE_TO




10001
SAR
2022-01-01 00:00:00
2022-12-31 23:59:59




And, for the sample data:
CREATE TABLE table_name (Item_no, item_type, active_from, active_to, rule_id) AS
SELECT 10001, 'SAR', DATE '2022-01-01', DATE '9999-12-31', 'rule1' FROM DUAL UNION ALL
SELECT 10001, 'SAR', DATE '2022-01-01', DATE '2023-05-31', 'rule2' FROM DUAL;

Outputs:




ITEM_NO
ITEM_TYPE
ACTIVE_FROM
ACTIVE_TO




10001
SAR
2023-05-31 00:00:01
9999-12-31 00:00:00




fiddle