determine if date is consecutive by person ID

jvoconnell
jvoconnell used Ask the Experts™
on
Experts,

I have a table with a member id and an eligibility date. I need to create a record by member id with the minimum eligibility date and max eligibility date where the dates are consecutive (by month). The logic is also that there can be be a one month gap to be considered "consecutive". When the dates aren't consecutive, it would be a new record.

MemberID        EligibilityDT
-----------------------------------------
XYZ                         1/1/2014
XYZ                         2/1/2014
XYZ                        4/1/2014
XYZ                        7/1/2014

The desired output would be:

MemberID      StartDT       EndDT
-----------------------------------------------
XYZ                1/1/2014      4/1/2014
XYZ               7/1/2014        7/1/2014


My logic is cursor processing. I am looping thru by member and comparing a date variable to the next date variable by DateDiff. Then swithcing the value of the date variable vs. the next date.

Am I  even correct that cursor processing is the way to go. It just seems like there has to be an easier way.
The table has 10M rows. Any insight is appreciated.

SQL Server 2012 if that matters.

Thank you.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
PortletPaulEE Topic Advisor
Most Valuable Expert 2014
Awarded 2013

Commented:
SQL Server 2012 if that matters = thank you, thank you, thank you - knowing version is always important
Top Expert 2013
Commented:
This query will get you the desired result:
with dates as(
  select MemberID, 
  EligibilityDT,
  row_number() OVER(PARTITION BY MemberID ORDER BY EligibilityDT) RN,
  LAG(EligibilityDT, 1, EligibilityDT) OVER(PARTITION BY MemberID ORDER BY EligibilityDT) PreviousDT,
  MAX(EligibilityDT) OVER(PARTITION BY MemberID) MaxDate
  FROM Table1
),
startDates AS(
  SELECT MemberID, EligibilityDT,
  CASE WHEN rn = 1 OR DATEDIFF(m, PreviousDT, EligibilityDT) >2 THEN EligibilityDT END StartDate, 
  PreviousDT,
  MaxDate
  FROM dates ),
startEndDates AS(
  SELECT MemberID, StartDate,
  LEAD(PreviousDT, 1, MaxDate) OVER(PARTITION BY MemberID ORDER BY StartDate) EndDate
  FROM startDates WHERE StartDate IS NOT NULL)
SELECT  * from startEndDates
ORDER BY 1,2

Open in new window

Results:
    CREATE TABLE Table1
    	([MemberID] varchar(3), [EligibilityDT] datetime)
    ;
    	
    INSERT INTO Table1
    	([MemberID], [EligibilityDT])
    VALUES
    	('XYZ', '2014-01-01 11:00:00'),
    	('XYZ', '2014-02-01 11:00:00'),
    	('XYZ', '2014-04-01 11:00:00'),
    	('XYZ', '2014-07-01 10:00:00'),
    	('YYZ', '2014-01-01 11:00:00'),
    	('YYZ', '2014-05-01 10:00:00'),
    	('YYZ', '2014-06-01 10:00:00'),
    	('YYZ', '2014-08-01 10:00:00')
    ;

    | MEMBERID |                      STARTDATE |                        ENDDATE |
    |----------|--------------------------------|--------------------------------|
    |      XYZ | January, 01 2014 11:00:00+0000 |   April, 01 2014 11:00:00+0000 |
    |      XYZ |    July, 01 2014 10:00:00+0000 |    July, 01 2014 10:00:00+0000 |
    |      YYZ | January, 01 2014 11:00:00+0000 | January, 01 2014 11:00:00+0000 |
    |      YYZ |     May, 01 2014 10:00:00+0000 |  August, 01 2014 10:00:00+0000 |

Open in new window

PortletPaulEE Topic Advisor
Most Valuable Expert 2014
Awarded 2013

Commented:
LEAD() LAG() were introduced at SQL 2012 so  it was worth knowing.

Well done chaau!

--
just in case: no points please
Should you be charging more for IT Services?

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
Wow! This is great. I new I was attacking this the wrong way. Thank you so much!!  Thank you both for jumping in.
Top Expert 2013

Commented:
Thanks for that. I am curious how performant the query is. Have you tried against your 10M records? How fast was it?

Author

Commented:
Performance is awesome! We decided to go back even further in history. We have 24M rows and the query finished in 22 seconds. My cursor logic was running at @ 3 hours for a small sampling of data. THANK YOU AGAIN!
PortletPaulEE Topic Advisor
Most Valuable Expert 2014
Awarded 2013

Commented:
Thanks for the feedback.

Take it as a lesson to use "set based" operations in SQL whenever you can and use cursors only where they are absolutely the only option :)

Cheers, Paul

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial