简体   繁体   中英

Finding gap between dates in sql for a particular month

I have 4 columns `BenefitKey, MemberKey, StartDate, Enddate` in a table

Given data like this:

    StartDate         Enddate
    ------------------------------
    20110315           20110316 
    20110317           20110320
    20110321           20110325
    20110326           20121202
    20121203           20121210
    20121211           20121215
    20121225           20121231

I need to find the missing gap between the month of December and fill the gap using a SQL query 

Here the missing gap is from `20121216` to `20121224`. I have 1000 rows like this, so I need a SQL query .i found some solution to it but still not correct here is what i wrote
CREATE TABLE #BenfitDim(MemberName varchar(30),Memberkey int,MemberEffectiveDate DATETIME, MemberTerminationDate DATETIME)


    INSERT INTO #BenfitDim VALUES('tom',231,'2012-11-18','2012-11-23')
    INSERT INTO #BenfitDim VALUES('tom',231,'2012-11-24','2012-12-12')
    INSERT INTO #BenfitDim VALUES('tom',231,'2013-01-01','2999-12-12')
    INSERT INTO #BenfitDim VALUES('jack',344,'2011-06-27','2012-12-07') 
    INSERT INTO #BenfitDim VALUES('jack',344,'2012-12-01','2015-12-31')
    INSERT INTO #BenfitDim VALUES('nick',243,'2012-12-01','2012-12-07')
    INSERT INTO #BenfitDim VALUES('joy',234,'2012-12-08','2012-12-14')
    INSERT INTO #BenfitDim VALUES('tim',364,'2012-12-25','2012-12-30')
    INSERT INTO #BenfitDim VALUES('tim',364,'2013-01-15','2013-01-30')
    INSERT INTO #BenfitDim VALUES('jerry',365,'2011-9-15','2012-12-31')
    INSERT INTO #BenfitDim VALUES('jerry',365,'2013-01-15','2013-01-30')
    INSERT INTO #BenfitDim VALUES('jerry',365,'2011-01-15','2012-01-30')




    SELECT MemberKey,
           MemberName,
           DATEADD(DAY,1,T1.MemberTerminationDate)AS MemberEffectiveDate,
           DATEADD(DAY,-1,D.MemberEffectiveDate)AS MemberTerminationDate
    FROM
           #BenfitDim AS T1 CROSS APPLY(
                                    SELECT MIN(MemberEffectiveDate)AS MemberEffectiveDate
                                      FROM #BenfitDim AS T
                                      WHERE T.MemberEffectiveDate > T1.MemberEffectiveDate 
                                      AND T.MemberKey = T1.MemberKey)D
     WHERE DATEADD(DAY,1,T1.MemberTerminationDate)  D.MemberEffectiveDate



Once you execute you will find the missing sequence but still there is slight problem how do we take care of an overlap data of "jack" in the table and get the missing sequence right .

Do you have a table that has a complete year of dates? If not, you need to create one to find missing dates. Otherwise, you can use a cursor which would be very slow.

Say your table is named "Benefits".

Would something along this line solve your problem?

SELECT A.EndDate + 1 AS GapFrom,
    (SELECT MIN(StartDate) - 1 
     FROM Benefits WHERE StartDate > A.EndDate) AS GapUntil
FROM Benefits A
LEFT JOIN Benefits B WHERE A.EndDate + 1 = B.StartDate
WHERE B.BenefitKey IS NULL

What you want to do is a self join where you are joining the prior record, something like:

SELECT …,startDate, endDate
  FROM Table t, Table t2
 WHERE t2.id=t1.id+1

(this assumes IDs are sequential, if not then do:

 WHERE t1.enddate < MIN(t1.startdate)

this should get you the next record in date sequence.

Then to plug the hole it's a simple matter of:

INSERT INTO table
   VALUES blah, blah, t.endDate+1, t2.startDate-1

(Pseudocode on the dates, you'll have to do the math with whatever functions your version supports, like DATEADD.)

If you data has this format, with no overlaps, then the following query gets you the gaps between two dates:

select enddate+1 as startdate,
       (select MIN(startdate) - 1 from t t2 where t2.startdate > t.enddate
       ) as enddate
from t
where enddate+1 not in (select startdate from t)

I'm using a correlated subquery here because, in my opinion, it makes the structure of the query clearer. The gap starts at enddate+1 and ends one day before the next start date. And, there is only a gap when enddate+1 is not itself a startdate.

If this is producing correct results, then you can insert these values into your table using:

insert into t(startdate, enddate)
    select enddate+1 as startdate,
           (select MIN(startdate) - 1 from t t2 where t2.startdate > t.enddate
           ) as enddate
    from t
    where enddate+1 not in (select startdate from t)

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