Reputation: 365
I have a table called periodDefinition with columns rowNum, periodSeq, startDate, endDate. I am trying to write a SQL query to find a gap between the endDate of one row and the startDate of the next row. Right now it's seeing a "gap" if the startDate of the next row isn't the exact same date as the endDate of the previous row.
Most advice seems to be to create a calendar temp table and double check against that, but due to work constriction policies, I cannot do that. Thanks for any advice you can give.
Sample Data:
rowNum: 1, periodSeq: 1, startDate: 09/01/2014, endDate: 09/30/2014
rowNum: 2, periodSeq: 2, startDate: 10/01/2014, endDate: 10/30/2014
rowNum: 3, periodSeq: 4, startDate: 11/01/2014, endDate: 11/30/2014
Test Query:
SELECT endDate, startDate
FROM
(
SELECT DISTINCT startDate, ROW_NUMBER() OVER (ORDER BY startDate) RN
FROM dbo.PeriodDefinition T1
WHERE
NOT EXISTS (
SELECT *
FROM dbo.PeriodDefinition T2
WHERE T1.startDate > T2.startDate AND T1.startDate < T2.endDate
)
) T1
JOIN (
SELECT DISTINCT endDate, ROW_NUMBER() OVER (ORDER BY endDate) RN
FROM dbo.PeriodDefinition T1
WHERE
NOT EXISTS (
SELECT *
FROM dbo.PeriodDefinition T2
WHERE T1.endDate > T2.startDate AND T1.endDate < T2.endDate
)
) T2
ON T1.RN - 1 = T2.RN
WHERE
endDate < startDate
Results:
endDate: 2014-09-30, startDate, 2014-01-01
endDate: 2014-09-30, startDate: 2014-11-01
endDate: 2014-10-30, startDate: 2014-12-01
Desired Results:
endDate: 2014-10-30, startDate: 2014-11-01
Upvotes: 1
Views: 3140
Reputation: 13949
If you are interested in getting the missing dates you could do something like this using a recursive cte.
WITH cte AS (
SELECT MIN(startDate) startDate,
MAX(startDate) endDate
FROM SampleData
UNION ALL
SELECT DATEADD(day, 1, startDate),
endDate
FROM cte
WHERE DATEADD(day, 1, startDate) <= endDate
)
SELECT cte.startDate
FROM cte
LEFT JOIN SampleData s ON cte.startDate BETWEEN s.startDate AND s.endDate
WHERE s.startDate IS NULL
OPTION (MAXRECURSION 0);
If you just want to use a query similar to yours, you can just use
SELECT
endDate,
startDate
FROM
(SELECT startDate,
ROW_NUMBER () OVER (ORDER BY startDate) RN
FROM PeriodDefinition T1
) T1
JOIN (SELECT endDate,
ROW_NUMBER () OVER (ORDER BY endDate) RN
FROM PeriodDefinition T1
) T2 ON T1.RN - 1 = T2.RN
WHERE
endDate + 1 < startDate
the problem with your query, that I saw, was that you were not adding 1 to the endDate in your where
Upvotes: 1
Reputation: 31785
Assuming that rowNum
is sequential with no gaps.
Here's a simple way to get your desired result:
SELECT t1.EndDate, t2.StartDate
FROM PeriodDefinition t1
INNER JOIN PeriodDefinition t2
ON t1.rowNum=t2.rowNum - 1
WHERE DATEDIFF(day, t1.EndDate, t2.StartDate)>1
Upvotes: 3