TSQL - 递归选择2个给定日期之间的日期

时间:2013-10-22 08:31:19

标签: sql tsql sql-server-2005 recursive-query

我的数据库中有一个名为Tasks的表。 该表中的每条记录都有2个字段:StartDateEndDate
我需要创建递归存储过程,在这些日期的中间发送邮件 例如:
开始时间为2013-10-22 12:00:00:000
结束是2013-10-24 12:00:00:000

我能做到:

SELECT DATEADD(ms, 
       DATEDIFF(ms,'2013-10-22 12:00:00:000', '2013-10-24 12:00:00:000')/2,
       '2013-10-22 12:00:00:000')

然后检查现在是否大于该日期,如果是,那么我可以发送邮件。

但是我需要递归地做到这一点:第一个主要必须是中间发送,第二个是1/4,第三个是1/8等,最后是剩下2个小时。

我的第一个想法是在我的表中添加列并在其中存储最后一个main的日期,但我想避免修改表。

我认为递归选择会更好,但欢迎任何有关如何解决的想法:)

编辑:我的样本小提琴:http://sqlfiddle.com/#!3/25d0d/1

我的例子:
任务从2013-10-22 8:00开始,到2013-10-22 21:00结束

程序从2013-10-22 10:00开始 第一条记录发送时间为14:30,所以无需发送

程序从2013-10-22 12:00开始 第一条记录发送时间为14:30,所以无需发送

程序从2013-10-22 14:00开始 第一条记录发送时间为14:30,所以无需发送

程序从2013-10-22 16:00开始 第一条记录发送时间为14:30,因此发送有关该任务的邮件

下一条消息应该在17:45左右发送

程序开始于2013-10-22 18:00

第一条记录发送时间为17:45,因此发送有关该任务的邮件

下一条消息应该在19:22左右发送

程序从2013-10-22 20:00开始 第一条记录的发送时间为19:22所以应该发送邮件,
但是因为从19:22到21:00不到2个小时就不需要邮件了

1 个答案:

答案 0 :(得分:1)

无法在SQL Server 2005上进行测试,但在SQL Server 2008上,您可以使用递归公用表表达式(使用过程参数替换下面的固定日期)。第一部分是第一部分,第二部分是继续计算最后一次和结束时间之间的时间,直到时间差小于4小时;

WITH cte AS (
  SELECT DATEADD(ms, 
                 DATEDIFF(ms, '2013-10-22 12:00:00:000', 
                              '2013-10-24 12:00:00:000')/2,
                              '2013-10-22 12:00:00:000'
                               ) a
  UNION ALL
  SELECT DATEADD(ms, DATEDIFF(ms,cte.a, '2013-10-24 12:00:00:000')/2, cte.a)
  FROM cte
  WHERE DATEDIFF(hour, cte.a, '2013-10-24 12:00:00:000') >= 4
)
SELECT * FROM cte;

An SQLfiddle to test with

编辑:要获得具有过去2小时内邮件时间的任务(即应生成邮件),您可以使用类似的内容;

WITH cte AS (
  SELECT taskid,enddate, DATEADD(s, 
                  DATEDIFF(s, startdate, enddate)/2, startdate) tm
  FROM Tasks
  UNION ALL
  SELECT taskid,enddate, DATEADD(ms, DATEDIFF(ms,cte.tm, enddate)/2, cte.tm)
  FROM cte
  WHERE DATEDIFF(hour, cte.tm, enddate) >= 4
)
SELECT taskid, tm FROM cte WHERE tm < GETDATE() AND DATEDIFF(hour, tm, GETDATE()) < 2

如果作业以不规则的间隔运行,您可能希望将GETDATE()截断为几小时。