【问题标题】:Find Date Gap Between Consecutive Start/End Date Columns查找连续开始/结束日期列之间的日期间隔
【发布时间】:2015-10-27 19:19:22
【问题描述】:

我有一个名为 periodDefinition 的表,其中包含 rowNum、periodSeq、startDate、endDate 列。我正在尝试编写一个 SQL 查询来查找一行的 endDate 和下一行的 startDate 之间的差距。现在,如果下一行的 startDate 与上一行的 endDate 的日期不完全相同,它就会看到一个“差距”。

大多数建议似乎是创建一个日历临时表并仔细检查,但由于工作限制政策,我不能这样做。感谢您提供的任何建议。

样本数据:

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

测试查询:

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

结果:

结束日期:2014 年 9 月 30 日,开始日期,2014 年 1 月 1 日

结束日期:2014-09-30,开始日期:2014-11-01

结束日期:2014-10-30,开始日期:2014-12-01

期望的结果:

结束日期:2014-10-30,开始日期:2014-11-01

【问题讨论】:

  • 这是一篇非常深入的文章,涵盖了这个主题。 sqlservercentral.com/articles/T-SQL/123609
  • 太糟糕了,贵公司对创建一些实用程序表以使事情变得更容易和更快有如此奇怪的限制。 >.
  • @SeanLange 长话短说,这是因为需要有一个临时表,其中包含可能追溯到几十年前的历史日期。
  • 但是日历表不应该是临时表。它应该是一张永久的桌子。不允许日历表就像不允许计数表一样。当然我仍然可以获取数据,但是如果没有,一些查询会慢很多。
  • 我不了解您的示例数据。你从哪里拉2014-01-012014-12-01?您是否只希望获得所需结果中的那一行?

标签: sql-server date


【解决方案1】:

假设rowNum 是连续的,没有间隙。

这是获得所需结果的简单方法:

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

【讨论】:

    【解决方案2】:

    如果您有兴趣获取缺失的日期,您可以使用递归 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);
    

    SQL Fiddle

    如果您只想使用与您类似的查询,则可以使用

    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
    

    SQL Fiddle

    我看到,您的查询的问题是您没有在 where 的 endDate 中添加 1

    【讨论】:

    • OP 的预期结果需要 EndDate 和 StartDate。此查询将仅返回 StartDate。
    • 那是真的.. 获取结果集并找到 endDate 和 startDate 并不难.. 比尝试保持 rowNum 顺序没有间隙更容易:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多