我正在尝试编写一个查询来获取会员的连续订阅日期,但无法拉取像下面这样的场景,其中会员的几个日期范围的 end_date 重叠,请帮助在 oracle 中提供逻辑/查询。
身份证 | 开始日期 | 结束日期 |
---|---|---|
12345 | 15 年 8 月 7 日 | 65 年 8 月 7 日 |
12345 | 2015 年 8 月 22 日 | 2016 年 1 月 1 日 |
12345 | 2016 年 3 月 24 日 | 66 年 3 月 23 日 |
12345 | 2016 年 7 月 6 日 | 2017 年 12 月 31 日 |
12345 | 2016 年 12 月 31 日 | 41 年 12 月 31 日 |
4662828 | 2015 年 8 月 22 日 | 2015 年 12 月 22 日 |
4662828 | 2016 年 1 月 1 日 | 2018 年 8 月 1 日 |
4662828 | 2017 年 6 月 10 日 | 2018 年 12 月 31 日 |
4662828 | 2018 年 12 月 1 日 | 72 年 12 月 4 日 |
身份证 | 开始日期 | 结束日期 |
---|---|---|
12345 | 15 年 8 月 7 日 | 66 年 3 月 23 日 |
4662828 | 2015 年 8 月 22 日 | 2015 年 12 月 22 日 |
4662828 | 2016 年 1 月 1 日 | 72 年 12 月 4 日 |
以下是我正在使用的逻辑,但它没有给出预期的结果,请帮忙。
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 >= start_date AND PRIOR end_date < 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](https://dbfiddle.uk/VGbdPntE)