【问题标题】:TSQL - Recursively select date between 2 given datesTSQL - 在两个给定日期之间递归选择日期
【发布时间】:2013-10-22 18:18:31
【问题描述】:

我的数据库中有一个名为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')

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

但我需要递归地执行此操作:第一个 main 必须在中间发送,第二个在 1/4 中,第三个在 1/8 等等,最后在剩下 2 小时时发送。

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

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

编辑:我的小提琴样例: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 小时,所以不需要邮件

【问题讨论】:

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


    【解决方案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() 截断为几小时。

    【讨论】:

    • 太棒了 :) 它在 2005 年运行良好。还有一件事。因为我将每 2 小时在工作中触发一次程序,我该如何选择我要发送邮件的那些任务?我会修改我的小提琴来展示我的想法
    • 我没有注意到您的回答中的编辑。我会马上检查的:)
    猜你喜欢
    • 1970-01-01
    • 2017-03-07
    • 2015-07-08
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    相关资源
    最近更新 更多