determine if date is consecutive by person ID


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.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SQL Server 2012 if that matters = thank you, thank you, thank you - knowing version is always important
This query will get you the desired result:
with dates as(
  select MemberID, 
  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, 
  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

Open in new window

    	([MemberID] varchar(3), [EligibilityDT] datetime)
    INSERT INTO Table1
    	([MemberID], [EligibilityDT])
    	('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


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LEAD() LAG() were introduced at SQL 2012 so  it was worth knowing.

Well done chaau!

just in case: no points please
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

jvoconnellAuthor Commented:
Wow! This is great. I new I was attacking this the wrong way. Thank you so much!!  Thank you both for jumping in.
Thanks for that. I am curious how performant the query is. Have you tried against your 10M records? How fast was it?
jvoconnellAuthor 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!
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft SQL Server

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.