Oracle 基于开始日期和结束日期拆分日期

Oracle 基于开始日期和结束日期拆分日期,oracle,oracle11g,oracle10g,oracle-sqldeveloper,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 SELEC

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

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!

假设您实际使用的是Oracle,并且它是一个相当新的版本,即11gR2或更高版本,而不是您标记问题时的10g版本,那么您可以使用来执行拆分。进一步假设您不希望分割超过当前月份,您可以使用大小写表达式来决定是分割还是保留原始(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;

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


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

表名和insert语句对Oracle都无效,并且“01/10/2020”是字符串而不是日期。假设它实际上是针对Oracle的,哪个版本,正如您标记的两个版本?到目前为止,你尝试过什么?还有,为什么第二排的扩展,2020-03-22到9999-12-31,会分成几个月,然后在2020-07-01停止?因为那可能是本月吧?请编辑你的问题来解释你的逻辑。亚历克斯,这太棒了,我正在全力以赴,如果我看到任何问题,我一定会联系你。
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