复杂的SQL日期逻辑:如何安排我的报告?

时间:2012-02-29 10:32:50

标签: sql sql-server tsql logic

我的表格看起来像这样(简化):

*ScheduledReports*
ReportID  
StartDate  
Frequency  
Interval (1=months, 2=days)

因此,如果我想每3天运行一次报告,频率为3,间隔为2。

我正在尝试编写一个我们每天可以运行一次的存储过程,它将运行今天安排的表中的所有报告(或者应该自上次运行存储过程以来运行)。

存储过程还可以访问lastRunTime(上次运行此存储过程)。

这是我的查询到目前为止的样子:

-- get monthly reports that should be run
SELECT reportID
FROM ScheduledReports
WHERE intervalType = 1 AND
    dateadd(m,  (
           frequency * ceiling((
              --sql server calculates datediff of months based on the actual int of the month
              --not if it's a true month later, so the following is necessary to check for
              --a dayOfMonth difference
              CASE
                  WHEN startDate > @lastRunTime
                         THEN 0
                  WHEN day(startDate) > day(@lastRunTime)
                         THEN datediff(m, startDate, @lastRunTime) - 1
                  ELSE datediff(m, startDate, @lastRunTime)
                  END
              ) / (frequency*1.0))
           ), startDate) BETWEEN @lastRunTime AND getDate()

UNION ALL

-- get weekly reports that should be run 
SELECT reportID
FROM ScheduledReports
WHERE intervalType = 2 AND
    dateadd(d, (
           frequency * ceiling((
              CASE
                  WHEN startDate > @lastRunTime
                         THEN 0
                  ELSE datediff(d, startDate, @lastRunTime)
                  END
              ) / (frequency*1.0)
           )), startDate) BETWEEN @lastRunTime AND getDate()

虽然逻辑上有一些东西。我的逻辑出了什么问题?我怎么能做到这一点?

2 个答案:

答案 0 :(得分:1)

  

存储过程还可以访问lastRunTime(上次运行此存储过程)。

您是否需要知道每个报告的最后一次生成?而不是最后一次这个sproc运行?每次运行sproc时,都可能生成或不生成每个报告。为了知道每个报告的间隔时间是否已经过去(3天,1个月等),您需要知道上次生成该报告的时间。

如果向表中添加LastReportRun日期列,该怎么办?然后不要针对@lastRunTime测试今天的日期,而是针对LastReportRun。

Report Run Today; Today = 2012/04/15

ID  StartDate   Freqcy  Interval  LastReportRun
--  ----------  ------  --------  ----------------  
1    2000/01/01  1      Days      2012/04/14         1 day ago;    print it
2    2000/01/01  14     Days      2012/04/09         6 days ago;   don`t print it
3    2000/01/01  3      Months    2012/01/13         > 3 mos ago;  print it
4    2000/01/01  3      Months    2012/01/17         < 3 mos ago;  don`t print it

答案 1 :(得分:0)

我们设法修复了这个错误 - 我们应该在这个案例中添加1,而不是减去,因为我们想要获得下一个运行日期,而不是之前的运行日期。将月份案例更改为:

 CASE
        WHEN startDate > @lastRunTime
              THEN 0
        WHEN day(startDate) > day(@lastRunTime)
              THEN datediff(m, startDate, @lastRunTime)
        ELSE datediff(m, startDate, @lastRunTime) + 1
 END

和日期案例:

CASE
     WHEN startDate > @lastRunTime
        THEN 0
     ELSE datediff(d, startDate, @lastRunTime) + 1
END

现在它完美地运作了:)