根据开始日期和结束日期拆分日期

时间:2020-07-23 08:49:27

标签: oracle oracle11g oracle10g oracle-sqldeveloper

我正在寻求有关日期分割的帮助,日期也可以在月份之间开始。下面是示例代码和输出。由于已故者,某些分裂可能会在中间结束。

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!

1 个答案:

答案 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   

db<>fiddle

锚成员从您的表中获取数据,保留原始的完整结束日期,并根据案例表达式确定该行的“拆分”结束日期,以检查当前月份,然后检查结束日期或去世日期。

如果行被拆分,则递归成员从下个月的第一天开始,仍保留原始的完整结束日期,并重复逻辑以确定该拆分的结束日期。它会递归地执行此操作(因此命名),直到到达原始完整结束日期的已故日期为止。

相关问题