C# 如何在sql server 2008中查找缺少的日期范围?
我的数据如下所示。 如何从ss表中查找缺少的日期范围 我想找到SEU startdate和SEU enddate之间的缺失日期范围 例如上面的例子 缺少的日期范围是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
可能有一种更简单的方法可以做到这一点,但通常在试图查找缺失的数字/日期时,您需要创建这些数字/日期,然后左键连接到现有数据以查找缺失的内容。您可以使用递归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
)