我正在try 编写一个查询以获取会员的连续订阅日期,但无法提取如下场景,其中end_Date在会员的几个日期范围内重叠,请帮助在Oracle中提供逻辑/查询.

[Data表中][1]

ID Start_date End_date
12345 07-Aug-15 07-Aug-65
12345 22-Aug-15 01-Jan-16
12345 24-Mar-16 23-Mar-66
12345 06-Jul-16 31-Dec-17
12345 31-Dec-16 31-Dec-41
46628 22-Aug-15 22-Dec-15
46628 01-Jan-16 01-Aug-18
46628 10-Jun-17 31-Dec-18
46628 01-Dec-18 04-Dec-72

[预期数据][2]

ID Start_date End_date
12345 07-Aug-15 23-Mar-66
46628 22-Aug-15 22-Dec-15
46628 01-Jan-16 04-Dec-72

以下是我正在使用的逻辑,但没有给出预期的结果,请帮助.

    SELECT ID, 
        START_DATE, 
        END_DATE 
    FROM (
        SELECT ID,
            CONNECT_BY_ROOT START_DATE START_DATE,
            DAYS_DIFF, 
            END_DATE,
            PREV_END,
            CONNECT_BY_ISLEAF ISLEAF
        FROM ( 
            SELECT ID,
                DAYS_DIFF,PREV_END, START_DATE,END_DATE   
            FROM (   
                SELECT ID,
                    ROUND(START_DATE-PREV_END) DAYS_DIFF,
                    CASE 
                        WHEN START_DATE<=PREV_END THEN PREV_END 
                    END PREV_END, 
                    START_DATE,END_DATE
                FROM ( 
                    SELECT ID,
                        LAG(END_DATE) OVER (PARTITION BY ID ORDER BY START_DATE) PREV_END, 
                        START_DATE,
                        END_DATE  
                    FROM TEST_TABLE A 
                )                  
            )     
        ) 
        CONNECT BY ID= PRIOR ID AND   PREV_END=  PRIOR END_DATE    START WITH PREV_END IS NULL  
    ) WHERE ISLEAF=1; 

推荐答案

这是一个可以得到您预期结果的查询

WITH tmp AS
(
    SELECT 12345 AS id,     TO_DATE('07-Aug-15', 'DD/MON/YY') AS Start_date,    TO_DATE('07-Aug-65', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 12345 AS id,     TO_DATE('22-Aug-15', 'DD/MON/YY') AS Start_date,    TO_DATE('01-Jan-16', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 12345 AS id,     TO_DATE('24-Mar-16', 'DD/MON/YY') AS Start_date,    TO_DATE('23-Mar-66', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 12345 AS id,     TO_DATE('06-Jul-16', 'DD/MON/YY') AS Start_date,    TO_DATE('31-Dec-17', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 12345 AS id,     TO_DATE('31-Dec-16', 'DD/MON/YY') AS Start_date,    TO_DATE('31-Dec-41', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    
    SELECT 4662828 AS id,   TO_DATE('22-Aug-15', 'DD/MON/YY') AS Start_date,    TO_DATE('22-Dec-15', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 4662828 AS id,   TO_DATE('01-Jan-16', 'DD/MON/YY') AS Start_date,    TO_DATE('01-Aug-18', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 4662828 AS id,   TO_DATE('10-Jun-17', 'DD/MON/YY') AS Start_date,    TO_DATE('31-Dec-18', 'DD/MON/YY') AS End_date FROM dual UNION ALL
    SELECT 4662828 AS id,   TO_DATE('01-Dec-18', 'DD/MON/YY') AS Start_date,    TO_DATE('04-Dec-72', 'DD/MON/YY') AS End_date FROM dual 
)
, tmp1 AS
(
    SELECT 
        CONNECT_BY_ROOT t.start_date AS start_date,
        t.id,
        t.start_date AS start_date1,
        t.end_date,
        level AS lvl
    FROM tmp t
    CONNECT BY PRIOR id = id AND PRIOR start_date <> start_date AND PRIOR end_date <> end_date 
        AND PRIOR end_date BETWEEN start_date AND end_date
)
, tmp2 AS 
(
    SELECT *
    FROM tmp1
    WHERE (start_date, id, lvl) IN
        (
            SELECT start_date, id, MAX(lvl)
            FROM tmp1
            GROUP BY start_date, id
        )
)
SELECT id,
    MIN(start_date) AS start_date,
    end_date
FROM tmp2
GROUP BY id, end_date
ORDER BY id, start_date;
ID START_DATE END_DATE
12345 07-AUG-15 23-MAR-66
4662828 22-AUG-15 22-DEC-15
4662828 01-JAN-16 04-DEC-72

fiddle

Sql相关问答推荐

如何在SQL查询中只比较日期时间的年份和月份(而忽略日期比较)?

为表中每个缺少的引用创建新行

如何根据计数和分组获取订单总数

如何在SQL中更新Json字符串

每年独特口味的冰淇淋数量

将所有XML文件导入到SQL Server中

缺少日期标识

SQL:查询作为子查询或CTE写入的最大和数失败

输出连续出现两次以上的行

Postgresql - WHERE 中的 MAX 标准 - 初学者问题

根据标识符将两行合并为一行

使用 Oracle SQL Developer 将不同的列值转换为列会导致错误 ORA-01489

从另一个没有公共键的表中获取值来加入

返回给定日期后的第 4 个工作日(不包括公众假期)

带聚合函数的 percentile_cont

计数时如何为所有时间间隔返回 0 而不是什么都不返回

使用SQL中另一个表的查询结果在表中查找记录

基于源表的 SQL INSERT、UPDATE 和 DELETE

为什么 Oracle 在一个查询中对同一张表同时执行 TABLE SCAN 和 INDEX UNIQUE SCAN?

如何找到特定时间间隔内的最大和最小日期?