查找缺失的日期范围

发布于 2024-12-05 22:53:42 字数 756 浏览 0 评论 0原文

表 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

我需要查找表 1 中的内容而不是表 2 中的内容

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)。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枫林﹌晚霞¤ 2024-12-12 22:53:42

这在 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  

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  
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文