C# 如何在sql server 2008中查找缺少的日期范围?

C# 如何在sql server 2008中查找缺少的日期范围?,c#,sql,sql-server,sql-server-2008,C#,Sql,Sql Server,Sql Server 2008,我的数据如下所示。 如何从ss表中查找缺少的日期范围 我想找到SEU startdate和SEU enddate之间的缺失日期范围 例如上面的例子 缺少的日期范围是 可能有一种更简单的方法可以做到这一点,但通常在试图查找缺失的数字/日期时,您需要创建这些数字/日期,然后左键连接到现有数据以查找缺失的内容。您可以使用递归cte创建相关日期: WITH cal AS (SELECT CAST('2014-07-01' AS DATE) dt UNION ALL

我的数据如下所示。

如何从ss表中查找缺少的日期范围

我想找到SEU startdate和SEU enddate之间的缺失日期范围

例如上面的例子

缺少的日期范围是


可能有一种更简单的方法可以做到这一点,但通常在试图查找缺失的数字/日期时,您需要创建这些数字/日期,然后左键连接到现有数据以查找缺失的内容。您可以使用递归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
然后,您需要使用DATEDIFF和ROW_NUMBER找出连续行是否属于同一范围,或者它们之间是否有间隙:

演示:

注意:如果要检查的范围超过100天,则需要指定MAXRECURSION,0表示没有限制


注2:如果您的SE日期用于驱动完整的日期范围,则将cal cte从固定日期更改为分别使用MIN和MAX的查询。

缺少的范围必须从SE_StartDate或ss_EndDate+1开始。同样,它必须在se_EndDate或ss_StartDate-1结束。排列候选范围并丢弃重叠部分

这种方法的优点是,时间精度可以轻松调整为小时、分或秒,而无需枚举每个时钟滴答声


我尝试过使用view和while循环,但无法得到完整的逻辑。类似的问题:SS_StartDate是否可以早于se_StartDate或SS_EndDate是否可以晚于se_EndDate?换句话说-间隔se_startdate、se_enddate是否始终包括间隔SS_startdate、SS_enddate?是的,se_startdate和se_enddate始终包括SS_startdate和SS_enddate。它不能超出se_startdate和se_EndDate可能值得一读,因为使用递归cte可能是最糟糕的方法。也在SQL Server中。然而,加1仍然是因为逻辑是正确的。@GarethD好的注释,我在大多数情况下使用不存在,但在向他人解释如何做事时使用不多。序列上的链接中的堆叠cte方法非常聪明,我通常使用从主..spt_值v1,主..spt_值v2。。。但我想我会换的。
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
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
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
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)
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
)