简体   繁体   中英

Merge records with consecutive date ranges

I am trying to figure out how to combine multiple records together into one where the TERM Date of the first record is the day before the EFFective date in the other record.

Here's some sample data:

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)

I created a CTE that JOINs onto itself by DATE = DATE - 1 of the second record. unfortunately, it only combines two records and I haven't figured out how to make it recursive.

;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)

The problem with this method is that there can be three or more consecutive records that need to be combined into one.

ID 1 should have two records - one from 1/1/2017 - 6/30/2018 and one from 9/1/2018 - 12/31/78 .

ID 2 should also have two records - 2/1/2017 - 3/30/2018 and 6/1/2018 - 12/31/78 .

ID 3 should also have two records - 1/1/2017 - 10/31/2017 and 12/1/2017 - 12/31/78 .

How can I combine these records? The records will mostly have the first of the month for the start date and the last day of the month for the term date - I don't need to worry about the outliers.

I've looked into similar question but they only have two records that need to be combined and use the same method I used.

This is the type of stuff that LAG and LEAD are useful for.

;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 basically peaks into the next row, and includes the specified column from the peaked into row in this row. LAG does the previous row.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM