SQL日期分组-每个排列

SQL日期分组-每个排列,sql,sql-server,tsql,Sql,Sql Server,Tsql,当前在日期窗口中定义的多个记录存在问题。其中一些窗口交叉或多窗口交叉。 我需要做的是获得有效从和有效到的正确顺序窗口 以下是当前数据集: ╔═════╦═══════════════╦═════════════╗ ║ Row ║ EffectiveFrom ║ EffectiveTo ║ ╠═════╬═══════════════╬═════════════╣ ║ 1 ║ 7/12/2010 ║ 15/01/2012 ║ ╠═════╬═══════════════╬══════

当前在日期窗口中定义的多个记录存在问题。其中一些窗口交叉或多窗口交叉。 我需要做的是获得有效从和有效到的正确顺序窗口

以下是当前数据集:

╔═════╦═══════════════╦═════════════╗
║ Row ║ EffectiveFrom ║ EffectiveTo ║
╠═════╬═══════════════╬═════════════╣
║ 1   ║ 7/12/2010     ║ 15/01/2012  ║
╠═════╬═══════════════╬═════════════╣
║ 2   ║ 1/01/2012     ║ 31/12/2042  ║
╠═════╬═══════════════╬═════════════╣
║ 3   ║ 15/01/2012    ║ 17/04/2012  ║
╠═════╬═══════════════╬═════════════╣
║ 4   ║ 17/04/2012    ║ 15/11/2012  ║
╠═════╬═══════════════╬═════════════╣
║ 5   ║ 15/11/2012    ║ 1/06/2013   ║
╠═════╬═══════════════╬═════════════╣
║ 6   ║ 1/06/2013     ║ 9/09/2013   ║
╠═════╬═══════════════╬═════════════╣
║ 7   ║ 9/09/2013     ║ 21/01/2020  ║
╠═════╬═══════════════╬═════════════╣
║ 8   ║ 23/12/2016    ║ 28/12/2019  ║
╠═════╬═══════════════╬═════════════╣
║ 9   ║ 23/12/2016    ║ 21/02/2020  ║
╠═════╬═══════════════╬═════════════╣
║ 10  ║ 21/01/2020    ║ 1/01/2100   ║
╠═════╬═══════════════╬═════════════╣
║ 11  ║ 21/02/2020    ║ 24/06/2100  ║
╚═════╩═══════════════╩═════════════╝
该数据的预期输出如下所示:

╔═══════════╦═══════════════╦═════════════╗
║ Row       ║ EffectiveFrom ║ EffectiveTo ║
╠═══════════╬═══════════════╬═════════════╣
║ 1         ║ 7/12/2010     ║ 1/01/2012   ║
╠═══════════╬═══════════════╬═════════════╣
║ 1,2       ║ 1/01/2012     ║ 15/01/2012  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,3       ║ 15/01/2012    ║ 17/04/2012  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,4       ║ 17/04/2012    ║ 15/11/2012  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,5       ║ 15/11/2012    ║ 1/06/2013   ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,6       ║ 1/06/2013     ║ 9/09/2013   ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,7       ║ 9/09/2013     ║ 23/12/2016  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,7,8,9   ║ 23/12/2016    ║ 28/12/2019  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,7,9     ║ 28/12/2019    ║ 21/01/2020  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,9,10    ║ 21/01/2020    ║ 21/02/2020  ║
╠═══════════╬═══════════════╬═════════════╣
║ 2,9,10,11 ║ 21/02/2020    ║ 31/12/2042  ║
╠═══════════╬═══════════════╬═════════════╣
║ 9,10,11   ║ 31/12/2042    ║ 1/01/2100   ║
╠═══════════╬═══════════════╬═════════════╣
║ 11        ║ 1/01/2100     ║ 24/06/2100  ║
╚═══════════╩═══════════════╩═════════════╝

不幸的是,我的大脑似乎已经达到了极限,无法在SQL中找到解决方法。您可以生成时间框架,然后使用相关子查询或横向联接:

with dates as (
      select v.dte as fromdate,
             lead(v.dte) over (order by v.dte) as todate
      from t cross apply
           (values (effdate), (enddate)
           ) v(dte) 
      group by v.dte
     )
select t.rows, d.*
from dates cross apply
     (select string_agg(row, ',') as rows
      from t
      where dates.fromdate < t.enddate and
            dates.todate >= t.effdate
     ) t;

我最后做了以下几件事:

SELECT 
    ROW_NUMBER() OVER (ORDER BY RDate) AS 'DateRow',
    * 
    INTO #Windows FROM (
    SELECT EffectiveFrom    AS 'RDate'
    FROM #Windows
    UNION 
    SELECT EffectiveTo      AS 'RDate'
FROM #Windows) [Windows]
SELECT 
    [StartDate].RDate                                   AS 'Start',
    [EndDate].RDate                                     AS 'End'
FROM #Windows [StartDate]
    LEFT JOIN #Windows [EndDate] ON [StartDate].DateRow = [EndDate].DateRow - 1
一旦我正确地构建和订购了它,我就会执行以下操作:

SELECT 
    ROW_NUMBER() OVER (ORDER BY RDate) AS 'DateRow',
    * 
    INTO #Windows FROM (
    SELECT EffectiveFrom    AS 'RDate'
    FROM #Windows
    UNION 
    SELECT EffectiveTo      AS 'RDate'
FROM #Windows) [Windows]
SELECT 
    [StartDate].RDate                                   AS 'Start',
    [EndDate].RDate                                     AS 'End'
FROM #Windows [StartDate]
    LEFT JOIN #Windows [EndDate] ON [StartDate].DateRow = [EndDate].DateRow - 1
看起来效果很好,给了我预期的结果