我正在寻求有关日期分割的帮助,日期也可以在月份之间开始。下面是示例代码和输出。由于已故者,某些分裂可能会在中间结束。
Create Table #DATE_SPLIT
(
ID INT,
StartDate DATE,
EndDate DATE,
Deceased_Date DATE
)
INSERT INTO #DATE_SPLIT
SELECT 10,'01/10/2020','03/21/2020',NULL
UNION ALL
SELECT 10,'03/22/2020','12/31/9999',NULL
UNION ALL
SELECT 20,'01/01/2020','02/21/2020','03/20/2020'
UNION ALL
SELECT 20,'02/22/2020','12/31/9999','03/20/2020'
--OUTPUT
ID StartDate EndDate Deceased_Date
10 '01/10/2020' '01/31/2020' NULL
10 '02/01/2020' '02/29/2020' NULL
10 '03/01/2020' '03/21/2020' NULL
10 '03/22/2020' '03/31/2020' NULL
10 '04/01/2020' '04/30/2020' NULL
10 '05/01/2020' '05/31/2020' NULL
10 '06/01/2020' '06/30/2020' NULL
10 '07/01/2020' '12/31/9999' NULL
20 '01/10/2020' '01/31/2020' '03/20/2020'
20 '02/01/2020' '02/21/2020' '03/20/2020'
20 '02/22/2020' '02/29/2020' '03/20/2020'
20 '03/01/2020' '03/20/2020' '03/20/2020' ---LOOP Has to end here, since member is decease. thanks!
答案 0 :(得分:1)
假设您实际上正在使用Oracle,并且它是一个相对较新的版本-即11gR2或更高版本,而不是标记问题时的10g-那么您可以使用recursive subquery factoring进行拆分。进一步假设您不想拆分当前月份,则可以使用case表达式来决定拆分还是保留原始(9999-12-31)结束日期或已故日期。像这样:
with rcte (id, startdate, enddate, deceased_date, full_enddate) as (
select id,
startdate,
case
when trunc(startdate, 'MM') = trunc(sysdate, 'MM')
and enddate > sysdate then enddate
when deceased_date is null then least(last_day(startdate), enddate)
else least(last_day(startdate), enddate, deceased_date)
end,
deceased_date,
enddate
from date_split
union all
select id,
enddate + 1,
case
when trunc(enddate + 1, 'MM') = trunc(sysdate, 'MM')
and full_enddate > sysdate then full_enddate
when deceased_date is null then least(last_day(enddate + 1), full_enddate)
else least(last_day(enddate + 1), full_enddate, deceased_date)
end,
deceased_date,
full_enddate
from rcte
where enddate < least(full_enddate, nvl(deceased_date, full_enddate))
)
select id, startdate, enddate, deceased_date
from rcte
order by id, startdate;
其中包含您的示例数据的
ID | STARTDATE | ENDDATE | DECEASED_DATE
-: | :--------- | :--------- | :------------
10 | 2020-01-10 | 2020-01-31 | null
10 | 2020-02-01 | 2020-02-29 | null
10 | 2020-03-01 | 2020-03-21 | null
10 | 2020-03-22 | 2020-03-31 | null
10 | 2020-04-01 | 2020-04-30 | null
10 | 2020-05-01 | 2020-05-31 | null
10 | 2020-06-01 | 2020-06-30 | null
10 | 2020-07-01 | 9999-12-31 | null
20 | 2020-01-01 | 2020-01-31 | 2020-03-20
20 | 2020-02-01 | 2020-02-21 | 2020-03-20
20 | 2020-02-22 | 2020-02-29 | 2020-03-20
20 | 2020-03-01 | 2020-03-20 | 2020-03-20
锚成员从您的表中获取数据,保留原始的完整结束日期,并根据案例表达式确定该行的“拆分”结束日期,以检查当前月份,然后检查结束日期或去世日期。
如果行被拆分,则递归成员从下个月的第一天开始,仍保留原始的完整结束日期,并重复逻辑以确定该拆分的结束日期。它会递归地执行此操作(因此命名),直到到达原始完整结束日期的已故日期为止。