簡體   English   中英

如何在SQL Server 2008中找到缺少的日期范圍?

[英]How can I find missing date range in sql server 2008?

我的數據如下所示。 在此處輸入圖片說明

如何從SS表中找到缺少的日期范圍。

我想在se_startdate和se_enddate之間找到缺少的(ss日期范圍)日期范圍。

例如上面。

缺少日期范圍是

2014-07-01 to 2014-07-06
2014-07-18 to 2014-07-30.

可能有一種更簡單的方法來執行此操作,但通常在嘗試查找丟失的數字/日期時,需要創建這些數字/日期,然后將LEFT JOIN到現有數據中以查找丟失的內容。 您可以使用遞歸cte創建相關日期:

WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
              UNION  ALL
              SELECT DATEADD(DAY,1,dt)
              FROM cal
              WHERE dt < '2014-07-30')
SELECT *
FROM cal

然后,將LEFT JOIN到表中以獲取缺少日期的列表:

WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
              UNION  ALL
              SELECT DATEADD(DAY,1,dt)
              FROM cal
              WHERE dt < '2014-07-30')
SELECT DISTINCT cal.dt 
FROM  cal
LEFT JOIN YourTable a
   ON cal.dt BETWEEN CAST(SS_StartDate AS DATE) AND CAST(SS_EndDate AS DATE)
WHERE a.SS_StartDate IS NULL

然后,您需要使用DATEDIFF()ROW_NUMBER()來找出連續的行是否屬於同一范圍,或者它們之間是否有間隔:

WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
              UNION  ALL
              SELECT DATEADD(DAY,1,dt)
              FROM cal
              WHERE dt < '2014-07-30')
    ,dt_list AS (SELECT DISTINCT cal.dt 
                  FROM  cal
                  LEFT JOIN YourTable a
                    ON cal.dt BETWEEN CAST(SS_StartDate AS DATE) AND CAST(SS_EndDate AS DATE)
                  WHERE a.SS_StartDate IS NULL)        
SELECT dt
      ,DATEDIFF(D, ROW_NUMBER() OVER(ORDER BY dt), dt) AS dt_range
FROM dt_list

然后使用MIN()MAX()獲得范圍:

WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt
              UNION  ALL
              SELECT DATEADD(DAY,1,dt)
              FROM cal
              WHERE dt < '2014-07-30')
    ,dt_list AS (SELECT DISTINCT cal.dt 
                  FROM  cal
                  LEFT JOIN YourTable a
                    ON cal.dt BETWEEN CAST(SS_StartDate AS DATE) AND CAST(SS_EndDate AS DATE)
                  WHERE a.SS_StartDate IS NULL)        
    ,dt_range AS (SELECT dt
                         ,DATEDIFF(D, ROW_NUMBER() OVER(ORDER BY dt), dt) AS dt_range
                  FROM dt_list)
SELECT  MIN(dt) AS BeginRange
       ,MAX(dt) AS EndRange
FROM dt_range
GROUP BY dt_range;
--OPTION (MAXRECURSION 0)

演示: SQL Fiddle

注意:如果您要檢查的范圍超過100天,則需要指定MAXRECURSION ,0表示沒有限制。

注2:如果您的SE日期旨在推動完整的日期范圍,然后更改cal從固定日期使用CTE來查詢MIN()MAX()分別。

缺少的范圍必須從se_StartDate或ss_EndDate + 1開始。 同樣,它必須以se_EndDate或ss_StartDate-1結尾。 排列候選范圍並丟棄重疊部分。

此方法的優點是可以輕松地將時間精度調整為小時,分鍾或秒,而無需枚舉每個時鍾滴答。

SQL小提琴演示

SELECT DISTINCT
  range_start, range_end, se_StartDate, se_EndDate
FROM MyTable t1
CROSS APPLY (
  SELECT se_StartDate range_start
  UNION ALL
  SELECT DATEADD(day,1,SS_EndDate)
) rs
CROSS APPLY (
  SELECT se_EndDate range_end
  UNION ALL
  SELECT DATEADD(day,-1,SS_StartDate)
  FROM MyTable
  WHERE
    se_StartDate = t1.se_StartDate AND
    se_EndDate   = t1.se_EndDate AND
    SS_StartDate > range_start
) re
WHERE NOT EXISTS (
  SELECT 1
  FROM MyTable
  WHERE
    range_start < SS_EndDate AND
    range_end > SS_StartDate
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM