合并具有连续日期范围的记录

时间:2018-09-26 00:04:54

标签: sql sql-server tsql sql-server-2012

我试图弄清楚如何将多个记录组合成一个记录,其中第一个记录的TERM日期是另一个记录中生效日期的前一天。

以下是一些示例数据:

SELECT 1 AS MEM_ID, CAST('2017-01-01' AS DATE) AS EFF_DATE, CAST('2017-05-31' AS DATE) AS TERM_DATE
INTO #TEMP 
UNION 
SELECT 1 AS MEM_ID, CAST('2017-06-01' AS DATE) AS EFF_DATE, CAST('2018-01-31' AS DATE)
UNION 
SELECT 1 AS MEM_ID, CAST('2018-02-01' AS DATE) AS EFF_DATE, CAST('2018-06-30' AS DATE)
UNION 
SELECT 1 AS MEM_ID, CAST('2018-09-01' AS DATE) AS EFF_DATE, CAST('2078-12-31' AS DATE)
UNION 
SELECT 2 AS MEM_ID, CAST('2017-02-01' AS DATE) AS EFF_DATE, CAST('2017-04-30' AS DATE)
UNION 
SELECT 2 AS MEM_ID, CAST('2017-05-01' AS DATE) AS EFF_DATE, CAST('2018-03-31' AS DATE)
UNION 
SELECT 2 AS MEM_ID, CAST('2018-06-01' AS DATE) AS EFF_DATE, CAST('2018-06-30' AS DATE)
UNION 
SELECT 2 AS MEM_ID, CAST('2018-07-01' AS DATE) AS EFF_DATE, CAST('2078-12-31' AS DATE)
UNION 
SELECT 3 AS MEM_ID, CAST('2017-01-01' AS DATE) AS EFF_DATE, CAST('2017-10-31' AS DATE)
UNION 
SELECT 3 AS MEM_ID, CAST('2017-12-01' AS DATE) AS EFF_DATE, CAST('2018-03-31' AS DATE)
UNION 
SELECT 3 AS MEM_ID, CAST('2018-04-01' AS DATE) AS EFF_DATE, CAST('2018-06-30' AS DATE)
UNION 
SELECT 3 AS MEM_ID, CAST('2018-07-01' AS DATE) AS EFF_DATE, CAST('2078-12-31' AS DATE)

我创建了一个CTE,该CTE在第二条记录的DATE = DATE-1之前加入自身。不幸的是,它只合并了两个记录,我还没有弄清楚如何使其递归。

;WITH TEST AS (
SELECT DISTINCT MEM_ID,
    EFF_DATE,
    TERM_DATE, 
    ROW_NUMBER()OVER(ORDER BY MEM_ID, EFF_DATE) ROW_NUM
FROM #TEMP
)

SELECT * 
FROM TEST T 
INNER JOIN TEST T2 ON T.MEM_ID = T2.MEM_ID AND T.TERM_DATE = DATEADD(DAY, -1, T2.EFF_DATE)

此方法的问题在于可能需要将三个或更多连续记录合并为一个。

ID 1应该有两条记录-一条来自1/1/2017 - 6/30/2018,一条来自9/1/2018 - 12/31/78

ID 2还应该有两个记录-2/1/2017 - 3/30/20186/1/2018 - 12/31/78

ID 3还应该有两个记录-1/1/2017 - 10/31/201712/1/2017 - 12/31/78

如何合并这些记录?记录将大部分包含开始日期的月份的第一天和学期日期的月份的最后一天-我不需要担心异常值。

我研究了类似的问题,但是它们只有两条记录需要合并,并使用与我相同的方法。

1 个答案:

答案 0 :(得分:0)

这是LAG和LEAD有用的东西类型。

;WITH CTE AS (SELECT DISTINCT  MEM_ID,
                  EFF_DATE,
                  LEAD(EFF_DATE, 1, NULL) OVER (PARTITION BY MEM_ID ORDER BY MEM_ID, EFF_DATE) AS TERM_DATE
              FROM #TEMP
             )

SELECT MEM_ID,
       EFF_DATE,
       TERM_DATE, 
       DATEADD(DAY, -1, TERM_DATE) AS D2
FROM CTE;

LEAD基本上到达下一行,并包括从该行中达到峰值的指定列。 LAG执行上一行。