我正在尝试找到比较一系列数据范围以找到间隙的方法,但是我需要排除完全在另一个范围内的日期范围。一些示例数据:
PERSON_ID START_DATE END_DATE
0001 01/05/2014 30/11/2014
0001 01/06/2014 01/08/2014
0001 01/07/2014 01/11/2014
0001 01/12/2014 31/03/2015
我知道我可以使用LEAD函数将一行与下一行比较,看看有没有差距的地方,例如:
SELECT END_DATE
FROM
(SELECT t.*,
lead(START_DATE,1) OVER (ORDER BY START_DATE) AS next_date
FROM table t
)
WHERE END_DATE+1<>next_date;
问题在于这会带来误报。第二行和第三行日期范围完全包含在第一行中,因此不应包括在间隙计算中。我知道我需要修改LEAD函数中的偏移量参数,但我不确定为数百个人ID执行此操作的有效方法。有什么想法吗?
答案 0 :(得分:2)
您可以尝试以下方式:
SELECT person_id
, start_date + 1 start_date
, end_date - 1 end_date
FROM
(SELECT person_id
, end_date start_date
, lead(start_date) OVER
(PARTITION BY person_id
ORDER BY start_date) end_date
FROM
(SELECT person_id
, start_date
, max(end_date) KEEP
(DENSE_RANK LAST
ORDER BY end_date
, start_date
NULLS LAST) end_date
FROM
(SELECT person_id
, CONNECT_BY_ROOT start_date start_date
, end_date
FROM
(SELECT person_id
, start_date
, end_date
, min(start_date) OVER
(PARTITION BY person_id) min_start_date
, lag(end_date) OVER
(PARTITION BY person_id
ORDER BY end_date
, start_date) lag_end_date
FROM mytable)
START WITH
( start_date = min_start_date
OR start_date > lag_end_date + 1)
CONNECT BY
person_id = PRIOR person_id
AND start_date > PRIOR start_date
AND ( start_date <= PRIOR end_date + 1
OR PRIOR end_date IS NULL))
GROUP BY person_id
, start_date))
WHERE end_date IS NOT NULL
这将合并重叠范围,例如2014年4月1日至2014年5月31日以及2014年5月1日至2014年6月30日将被视为2014年4月1日至2014年6月30日的单一范围。它还将合并邻接范围,例如2014年4月1日至2014年4月30日以及2014年5月1日至2014年5月31日将被视为2014年4月1日至2014年5月31日的单一范围。如果您不希望如何处理这些条件,则需要更改此查询。
答案 1 :(得分:0)
既然你说你得到了假阳性,你可以通过做这样的事情把它变成阳性:
SELECT * FROM table t where END_DATE
NOT IN (SELECT END_DATE
FROM
(SELECT t.*,
lead(START_DATE,1) OVER (ORDER BY START_DATE) AS next_date
FROM table t
)
WHERE END_DATE+1<>next_date);
我希望它能为您提供一条线索,让您在不更改偏移量参数的情况下获得所需内容。