【问题标题】:Merge records with consecutive date ranges合并具有连续日期范围的记录
【发布时间】:2018-09-27 00:40:33
【问题描述】:

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

以下是一些示例数据:

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,它通过第二条记录的 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

如何合并这些记录?记录的开始日期主要是每月的第一天,学期日期的最后一天 - 我不需要担心异常值。

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

【问题讨论】:

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


    【解决方案1】:

    这是 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 执行上一行。

    【讨论】:

    • 我修复了查询的一些问题,以便它运行,但我看不出这如何有助于将数据减少到每个 ID 两行。如果我遗漏了什么,请告诉我。
    猜你喜欢
    • 2013-03-24
    • 1970-01-01
    • 2014-03-02
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 2014-12-16
    • 2011-08-19
    • 1970-01-01
    相关资源
    最近更新 更多