【问题标题】:Separating date ranges into separate segments in SQL在 SQL 中将日期范围分成单独的段
【发布时间】:2010-03-22 17:36:25
【问题描述】:

我有一个包含 2 个日期字段和一个标识符(id、fromdate 和 todate)的表格,这些日期以任何可能的方式重叠。我需要生成一个段列表,每个段都有一个开始和结束日期,描述该列表中的单独段。

例如:

id,  FromDate    ToDate
1,   1944-12-11, 1944-12-31
2,   1945-01-01, 1945-12-31
3,   1945-01-01, 1945-06-30
4,   1945-12-31, 1946-05-01
5,   1944-12-17, 1946-03-30

应该产生所有重叠的所有片段:

1,   1944-12-11, 1944-12-16
1,   1944-12-17, 1944-12-31
5,   1944-12-17, 1944-12-31
2,   1945-01-01, 1945-06-30
3,   1945-01-01, 1945-06-30
5,   1945-01-01, 1945-06-30
2,   1945-07-01, 1945-12-09
5,   1945-07-01, 1945-12-09
2,   1945-12-10, 1945-12-31
4,   1945-12-10, 1945-12-31
5,   1945-12-10, 1945-12-31
4,   1946-01-01, 1946-03-30
5,   1946-01-01, 1946-03-30
4,   1946-04-01, 1946-05-01

或者图表可能会有所帮助

INPUT
1 <---->
2       <----------->
3       <----->
4                 <---------->
5    <----------------->

OUTPUT
1 <->
1    <->
5    <->
2       <----->
3       <----->
5       <----->
2              <->
5              <->
2                 <->
4                 <->
5                 <->
4                    <->
5                    <->
4                       <---->

请帮忙

【问题讨论】:

    标签: sql date


    【解决方案1】:

    You can use this SO question's answer as a basis.

    它分成这个输出,但我认为它很容易变成你需要的:

    OUTPUT
    1                 <->
    1,5                  <->
    2,3,5                   <----->
    ...
    

    This link should also prove helpful - 它仅显示如何构建范围。

    【讨论】:

    • 没问题 :) 如果您有足够的代表进行投票,请随时为答案投票
    【解决方案2】:

    试试下面这个脚本

    架构

    CREATE TABLE splitDates
        ([member] int, effdt datetime, termdt datetime)
    ;
    
    INSERT INTO splitDates
        ([member], effdt, termdt)
    VALUES
    (1,   '1944-12-11', '1944-12-31'),
    (2,   '1945-01-01', '1945-12-31'),
    (3,   '1945-01-01', '1945-06-30'),
    (4,   '1945-12-31', '1946-05-01'),
    (5,   '1944-12-17', '1946-03-30');
    

    SQL 脚本

    DECLARE @SplitRanges TABLE ([member] int, theDate datetime, des varchar(10));
    
    INSERT INTO @SplitRanges
    SELECT  DISTINCT
     m.member, 
     memDt.theDate,
     memdt.des
    FROM splitDates m
    JOIN ( SELECT DISTINCT  effdt as theDate,'effdt' des FROM splitDates
        union all
        SELECT DISTINCT  effdt-1 as theDate,'trmdt' des FROM splitDates
        union all
        SELECT DISTINCT  termdt as theDate,'trmdt' des FROM splitDates
        union all
        SELECT DISTINCT  termdt+1 as theDate,'effdt' des FROM splitDates
        ) as memDt on 1=1
    WHERE memDt.theDate >= m.effdt 
      AND memDt.theDate <= m.termdt
    ORDER BY m.member, memdt.thedate;
    
    ;WITH rowNumbers as (
    SELECT ef.member, ef.thedate,ef.des, 
    ROW_NUMBER() over (PARTITION BY  ef.member ORDER BY ef.thedate ASC) AS rn
    FROM @SplitRanges ef
    )
    SELECT DISTINCT ef.member, ef.thedate as effdt, tm.thedate as termdt FROM rowNumbers ef
    JOIN rownumbers tm on tm.member=ef.member and ef.rn+1=tm.rn
    WHERE ef.des='effdt'
    order by ef.thedate
    

    输出

    member  effdt               termdt
    1   1944-12-11 00:00:00.000 1944-12-16 00:00:00.000
    1   1944-12-17 00:00:00.000 1944-12-31 00:00:00.000
    5   1944-12-17 00:00:00.000 1944-12-31 00:00:00.000
    2   1945-01-01 00:00:00.000 1945-06-30 00:00:00.000
    3   1945-01-01 00:00:00.000 1945-06-30 00:00:00.000
    5   1945-01-01 00:00:00.000 1945-06-30 00:00:00.000
    2   1945-07-01 00:00:00.000 1945-12-30 00:00:00.000
    5   1945-07-01 00:00:00.000 1945-12-30 00:00:00.000
    2   1945-12-31 00:00:00.000 1945-12-31 00:00:00.000
    4   1945-12-31 00:00:00.000 1945-12-31 00:00:00.000
    5   1945-12-31 00:00:00.000 1945-12-31 00:00:00.000
    4   1946-01-01 00:00:00.000 1946-03-30 00:00:00.000
    5   1946-01-01 00:00:00.000 1946-03-30 00:00:00.000
    4   1946-03-31 00:00:00.000 1946-05-01 00:00:00.000
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-14
      • 1970-01-01
      相关资源
      最近更新 更多