這裏是較舊的溶液(從評論中的一個),適用於純日期。您可能希望比較此處提供的不同解決方案,以查看哪一個對您的實際數據最有效;不同的解決方案可能適用於不同的情況。
注意:我使用了輸入數據並創建了一些用於測試的數據。假設您的數據有效(所有日期都有效,它們的時間分量爲00:00:00
,並且enddate
始終大於或等於startdate
)。該解決方案不包括inputs
因式分解子查詢,它僅在下面顯示用於測試。我沒有通過emp#
和startdate
(這方面的輸出可能會誤導)來排列結果;如果你確實需要這樣的順序,你需要明確地添加它。請注意在測試數據中使用date
文字。輸出顯示我當前會話設置中的日期;如果您需要特定的格式,請使用to_date()
以及所需的顯示格式型號。
QUERY:
with
inputs (emp#, startdate, enddate) as (
select 1, date '2016-01-01', date '2016-01-15' from dual union all
select 1, date '2016-01-03', date '2016-01-05' from dual union all
select 1, date '2016-01-10', date '2016-01-20' from dual union all
select 1, date '2016-01-23', date '2016-01-25' from dual union all
select 1, date '2016-01-24', date '2016-01-27' from dual union all
select 2, date '2016-01-31', date '2016-02-28' from dual union all
select 2, date '2016-03-15', date '2016-03-18' from dual union all
select 2, date '2016-03-19', date '2016-03-19' from dual union all
select 2, date '2016-03-20', date '2016-03-20' from dual
),
m (emp#, startdate, mdate) as (
select emp#, startdate,
1 + max(enddate) over (partition by emp# order by startdate
rows between unbounded preceding and 1 preceding)
from inputs
union all
select emp#, NULL, 1 + max(enddate)
from inputs
group by emp#
),
n (emp#, startdate, mdate) as (
select emp#, startdate, mdate
from m
where startdate > mdate or startdate is null or mdate is null
),
f (emp#, startdate, enddate) as (
select emp#, startdate,
lead(mdate) over (partition by emp# order by startdate) - 1
from n
)
select * from f where startdate is not null
OUTPUT(在inputs
CTE數據):
EMP# STARTDATE ENDDATE
------ ---------- ----------
1 01/01/2016 20/01/2016
1 23/01/2016 27/01/2016
2 31/01/2016 28/02/2016
2 15/03/2016 20/03/2016
請發表你嘗試過什麼至今。 – Aleksej
尋找「空白和島嶼問題」。 – mustaccio
我使用了自我連接,以便檢查兩個時間範圍之間是否有重疊 - 如果有的話我會選擇最小開始日期和最大結束日期。然後,我將選擇每個結束日期的最小開始日期和每個最小開始日期的最大結束日期。然而,如果我有兩個時間範圍都被第三個時間範圍重疊,這會讓我留下一些漏洞。 – Dezz