Reputation: 83053
I have a table that looks something like this (simplified):
*ScheduledReports*
ReportID
StartDate
Frequency
Interval (1=months, 2=days)
So if I would want to run a report every 3 days, frequency would be 3 and interval would be 2.
I'm trying to write a stored procedure that we can run once a day, that will run all reports from the table that are scheduled for today (or should have been run since the last time we ran the stored procedure).
The stored procedure also has access to the lastRunTime (the last time this stored procedure was run).
This is what my query looks like so far:
-- 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()
There is something off with the logic though. What is wrong with my logic? How can I accomplish this?
Upvotes: 4
Views: 741
Reputation: 83053
We managed to fix the bug - we were supposed to be adding 1 in the case, not subtracting, because we want to get the next run date, not the previous. Changed the month case to:
CASE
WHEN startDate > @lastRunTime
THEN 0
WHEN day(startDate) > day(@lastRunTime)
THEN datediff(m, startDate, @lastRunTime)
ELSE datediff(m, startDate, @lastRunTime) + 1
END
and the day case to:
CASE
WHEN startDate > @lastRunTime
THEN 0
ELSE datediff(d, startDate, @lastRunTime) + 1
END
And now it is working perfectly :)
Upvotes: 0
Reputation: 95
The stored procedure also has access to the lastRunTime (the last time this stored procedure was run).
Don't you need to know the last time each report was produced? And not the last time this sproc was run? Each time you run the sproc, each report may or may not be produced. In order to know if the interval for each report has passed for each report (3 days, 1 month, etc) you need to know when THAT report was last produced.
What if you add a LastReportRun date column to your table. Then don't test todays date against @lastRunTime, but rather against 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
Upvotes: 1