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?
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:
and the day case to:
And now it is working perfectly 🙂