Sql 计算日历期间内多个开始-停止记录之间的天数

Sql 计算日历期间内多个开始-停止记录之间的天数,sql,sql-server,date,Sql,Sql Server,Date,在给定的时间段内,活动可以启动和停止0次或更多次。每次这样做时,都会生成一个带有日期和操作的记录——我将这些操作称为“激活a”和“停用D”。我需要总结一个月内“活动”天数的总数。我想要一个简单的方法来做到这一点与例外和特殊情况整洁。我必须在tsql中执行此操作 以下是我迄今为止采取的程序方法: 在此期间是否有开始或停止事件? a如果没有,则查找时间段之前的最新事件 如果该事件已开始,则该期间的所有天都处于活动状态 ii如果事件停止,则该期间没有活动日 三、完成 b如果是的话,那就是程序性检查的老

在给定的时间段内,活动可以启动和停止0次或更多次。每次这样做时,都会生成一个带有日期和操作的记录——我将这些操作称为“激活a”和“停用D”。我需要总结一个月内“活动”天数的总数。我想要一个简单的方法来做到这一点与例外和特殊情况整洁。我必须在tsql中执行此操作

以下是我迄今为止采取的程序方法:

在此期间是否有开始或停止事件? a如果没有,则查找时间段之前的最新事件 如果该事件已开始,则该期间的所有天都处于活动状态 ii如果事件停止,则该期间没有活动日 三、完成 b如果是的话,那就是程序性检查的老鼠窝,如果是的话。 像往常一样,我希望了解其他人是如何看待这个问题的,而不是仅仅开始编写一个例程,按时间顺序对记录进行排序并循环遍历它们

典型数据集:

6/11/2014  A
6/20/2014  D
6/24/2014  A
6/26/2014  D
6/29/2014  A
这里的关注期是6月,第一个动作是激活,因此活动在6月11日之前一直处于非活动状态。同样地,在6月29日,事情再次活跃起来,因此这个月的剩余时间被视为活跃。在D和a日期上使用datediff函数,我得到9+2,一个月的最后一天总共有12个活动日

同样,仅对于一个周期的数据集,可能有0个或多个记录

当然,数据也可以是这样的:

6/11/2014  D
6/20/2014  A
6/24/2014  D
6/26/2014  A
6/29/2014  D
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select e, count(*) from dates GROUP BY e
OPTION (MAXRECURSION 0)
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select 
sum(case when e='A' THEN 1 ELSE 0 END) as A_days,
sum(case when e='D' THEN 1 ELSE 0 END) as D_days
from dates
OPTION (MAXRECURSION 0)
在这里,该活动一直处于“活动”状态,直到11月6日被停用。简单的日期区分D-A日期给了我额外的4+3天,总共17天


我担心如果我选择,排序然后做,而我将得到缠绕轴。我想知道其他人可能会采取什么更圆滑的方法。

此查询将为您提供给定时间段内的所有天数,以及当天的相应事件:

MS SQL Server 2008架构设置:

问题1:

使用上述查询,您将能够轻松生成计数查询,如下所示:

6/11/2014  D
6/20/2014  A
6/24/2014  D
6/26/2014  A
6/29/2014  D
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select e, count(*) from dates GROUP BY e
OPTION (MAXRECURSION 0)
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select 
sum(case when e='A' THEN 1 ELSE 0 END) as A_days,
sum(case when e='D' THEN 1 ELSE 0 END) as D_days
from dates
OPTION (MAXRECURSION 0)
或者像这样:

6/11/2014  D
6/20/2014  A
6/24/2014  D
6/26/2014  A
6/29/2014  D
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select e, count(*) from dates GROUP BY e
OPTION (MAXRECURSION 0)
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select 
sum(case when e='A' THEN 1 ELSE 0 END) as A_days,
sum(case when e='D' THEN 1 ELSE 0 END) as D_days
from dates
OPTION (MAXRECURSION 0)

此查询将为您提供给定期间的所有天,以及该天的相应事件:

MS SQL Server 2008架构设置:

问题1:

使用上述查询,您将能够轻松生成计数查询,如下所示:

6/11/2014  D
6/20/2014  A
6/24/2014  D
6/26/2014  A
6/29/2014  D
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select e, count(*) from dates GROUP BY e
OPTION (MAXRECURSION 0)
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select 
sum(case when e='A' THEN 1 ELSE 0 END) as A_days,
sum(case when e='D' THEN 1 ELSE 0 END) as D_days
from dates
OPTION (MAXRECURSION 0)
或者像这样:

6/11/2014  D
6/20/2014  A
6/24/2014  D
6/26/2014  A
6/29/2014  D
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select e, count(*) from dates GROUP BY e
OPTION (MAXRECURSION 0)
declare @start date, @end date
select @start = '2014-06-01', @end = '2014-06-30'
;with dates as (
  SELECT @start AS d, (SELECT TOP 1 CASE WHEN event = 'A' THEN 'D' ELSE 'A' END FROM Table1 ORDER BY dt) AS e
  UNION ALL 
  SELECT dateadd(day, 1, d), COALESCE((SELECT event FROM Table1 WHERE dt = dateadd(day, 1, dates.d)), dates.e)
  FROM dates 
  WHERE dates.d < @end)
select 
sum(case when e='A' THEN 1 ELSE 0 END) as A_days,
sum(case when e='D' THEN 1 ELSE 0 END) as D_days
from dates
OPTION (MAXRECURSION 0)

将表1定义为CTE是否合法,例如:表1 d,t为…,日期为[您的上述定义]?我还没有看到关于在同一范围内混合使用非递归和递归定义的参考。我不明白你的问题。好了:我想你可以自己试试……是的,我做了,它完全符合我的需要……工作完美。顺便说一句,如果你注意到我犯了一个错误。你需要自己修复它,非常容易修复。如果您在第1天有一个事件,即如果表中存在@start date的事件,则日期CTE中的初始e值将错误地设置为相反的事件。很容易修复,我将留给你自己。同样,在以下情况下,将表1定义为CTE是否合法:表1 d,t为…,日期为[你的上述定义]?我还没有看到关于在同一范围内混合使用非递归和递归定义的参考。我不明白你的问题。好了:我想你可以自己试试……是的,我做了,它完全符合我的需要……工作完美。顺便说一句,如果你注意到我犯了一个错误。你需要自己修复它,非常容易修复。如果您在第1天有一个事件,即如果表中存在@start date的事件,则日期CTE中的初始e值将错误地设置为相反的事件。很容易修复,由我自己决定