Reputation: 1262
Table 1
code StartDate EndDate
A 01/01/2011 06/15/2011
A 06/25/2011 06/30/2011
B 01/12/2011 07/31/2011
B 08/3/2011 12/31/2011
Table 2
code StartDate EndDate
A 01/01/2011 06/30/2011
B 01/12/2011 07/31/2011
B 08/3/2011 12/25/2011
I need find what is in Table1 and not in Table2 which is
code StartDate EndDate
B 12/26/2011 12/31/2011
And the Converse of what is in Table2 and not in Table1
code StartDate EndDate
A 06/16/2011 06/29/2011
There is no time component in the date field and T-SQL (SQL Server 2000 ) is preferred.
Upvotes: 0
Views: 278
Reputation: 454020
This is a bit tedious in SQL Server 2000. It uses a numbers table to expand out the ranges of dates into individual rows. Then NOT EXISTS
for the anti semi join then uses an "islands" approach I stole from an MSDN article to collapse the result back into ranges again.
SET DATEFORMAT MDY
DECLARE @Numbers TABLE (N INT PRIMARY KEY)
INSERT INTO @Numbers
SELECT number
FROM master..spt_values
WHERE type='P' AND number >= 0
DECLARE @Table1 TABLE
(
code CHAR(1),
StartDate DATETIME,
EndDate DATETIME
)
DECLARE @Table2 TABLE
(
code CHAR(1),
StartDate DATETIME,
EndDate DATETIME
)
INSERT INTO @Table1
SELECT 'A','01/01/2011','06/15/2011' UNION ALL
SELECT 'A','06/25/2011','06/30/2011' UNION ALL
SELECT 'B','01/12/2011','07/31/2011' UNION ALL
SELECT 'B','08/3/2011',' 12/31/2011'
INSERT INTO @Table2
SELECT 'A','01/01/2011','06/30/2011' UNION ALL
SELECT 'B','01/12/2011','07/31/2011' UNION ALL
SELECT 'B','08/3/2011',' 12/25/2011'
DECLARE @Results TABLE
(
code CHAR(1),
StartDate DATETIME
)
INSERT INTO @Results
SELECT T1.code,
DATEADD(DAY, N, StartDate)
FROM @Table1 T1
INNER JOIN @Numbers N1
ON N <= DATEDIFF(DAY, StartDate, EndDate)
WHERE NOT EXISTS (SELECT *
FROM @Table2 T2
INNER JOIN @Numbers N2
ON N2.N <= DATEDIFF(DAY, T2.StartDate, T2.EndDate)
WHERE DATEADD(DAY, N1.N, T1.StartDate) =
DATEADD(DAY, N2.N, T2.StartDate)
AND T1.code = T2.code)
/*SQL Server 2000 gaps and islands approach from here
http://msdn.microsoft.com/en-us/library/aa175780%28v=sql.80%29.aspx*/
SELECT t1.code,
t1.StartDate,
MIN(t2.StartDate) AS EndDate
FROM (SELECT StartDate,
code
FROM @Results tbl1
WHERE NOT EXISTS(SELECT *
FROM @Results tbl2
WHERE tbl1.StartDate = tbl2.StartDate + 1
AND tbl1.code = tbl2.code)) t1
INNER JOIN (SELECT StartDate,
code
FROM @Results tbl1
WHERE NOT EXISTS(SELECT *
FROM @Results tbl2
WHERE tbl2.StartDate = tbl1.StartDate + 1
AND tbl1.code = tbl2.code)) t2
ON t1.StartDate <= t2.StartDate
AND t1.code = t2.code
GROUP BY t1.code,
t1.StartDate
Upvotes: 5