找到缺少的日期范围

时间:2011-09-23 15:06:19

标签: tsql sql-server-2000

表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

表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

我需要找到Table1中的内容,而不是Table2中的

code        StartDate        EndDate
B           12/26/2011        12/31/2011

表2中的内容与表1中的内容相反

code        StartDate        EndDate
A           06/16/2011       06/29/2011

日期字段中没有时间组件,首选T-SQL(SQL Server 2000)。

1 个答案:

答案 0 :(得分:5)

这在SQL Server 2000中有点单调乏味。它使用数字表将日期范围扩展为单个行。然后NOT EXISTS用于反半连接,然后使用我从MSDN文章中窃取的“孤岛”方法将结果再次折叠回范围。

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