Job Execution Dates/Times Calculation (Past and Future Execution)

  • I have a tricky question to Microsoft SQL Server 2000/2005. I have failed to find a solution to the problem yet and others have failed too. So I thought that I throw it around here, because the fact that a lot of knowledgeable DBAs hang around in this forum.

    I am looking for a script/stored procedure that is able to show me upcoming job executions for a selected date/time range based on the current settings for the jobs configured on the Database server.

    Example

    Date/Time From:  2/16/2007 00:00 a.m. (Friday)

    Date/Time To:    2/17/2007 12:00 p.m. (Saturday)

    A.  Job 1 / Schedule 1 = Week Days, 1:00 a.m.

    B.  Job 1 / Schedule 2 = Saturdays, 10:00 a.m.

    C.  Job 2 / Schedule 1 = hourly, between 10:00 a.m. and 1:00 p.m.

    D.  Job 3 / Schedule 1 = every 3rd Saturday of the month, 5:00 a.m.

    E.  Job 4 / Schedule 1 = every 1st Friday of the month, 8:00 a.m.

    The routine I have in mind would not return Job E, because 2/16/2007 is the 3rd Friday of the month and not the first.

    Job A: 2/16/2007 01:00 a.m.

    Job B: 2/16/2007 10:00 a.m.

    Job B: 2/16/2007 11:00 a.m.

    Job B: 2/16/2007 12:00 p.m.

    Job B: 2/16/2007 01:00 p.m.

    Job D: 2/17/2007 05:00 a.m.

    Job A: 2/17/2007 10:00 a.m.

    Job B: 2/17/2007 10:00 a.m.

    Job B: 2/17/2007 11:00 a.m.

    Job B: 2/17/2007 12:00 p.m.

    Output

    1. It needs to return the Job ID, the Job Name, the Schedule ID, the Date and the Time.
    2. Disabled Jobs and Schedules are by default excluded from the selection, but an option to include or exclude those would be a bonus.
    3. Information such as the min, max and average execution time would be great too.

    Notes

    The schedules of Job D and Job B overlap as you can see in my example above.

    This happens only once per month though.  I have over 20 jobs with sometimes very frequent execution times, like every 5 minutes or every 20 minutes and jobs that run hourly, daily, weekdays only, weekends only, monthly once etc.

    Purpose

    I want to do two things.

    I want to determine where jobs overlap, not just by start date/time, but also by average run time and maximum run time.

    I also want to be able to generate a report that shows me what should have been done and what was actually done by the jobs (note on the site, 6 of the jobs create new jobs on the fly for other database servers and this is sometimes not happening properly, without getting any error message. The volume of jobs makes the manual search like a search for a needle in a haystack.)

    Findings so far

    I did some digging myself and found following stored procedures that do some of the steps that I need and involved tables for the calculation.

    Stored procedures:

    - sp_get_schedule_description (in db: msdb) (undocumented stored procedure)

    - sp_add_schedule (in db: msdb) http://msdn2.microsoft.com/en-us/library/ms187320.aspx

    Tables:

    - msdb.sysjobs

    - msdb.sysjobschedules

    - msdb.sysjobhistory 

    It is not a problem to determine the next execution of a job, but that is not what I need, anyway.

    The problem is that it does not help you to determine all upcoming execution times, if the selected timeframe is long enough that SQL Server executes the job more than once.

    There is no way around using the sysjobschedules table and calculate the execution dates and times based on the configured settings. See the Stored procedure: sp_get_schedule_description.

    That one breaks down nicely the settings as documented for sp_add_schedule at

    http://msdn2.microsoft.com/en-us/library/ms187320.aspx, but it does not allow the determination of the exact upcoming dates and times when the job is supposed to be executed.

    Does anybody has a script that does that or several individual scripts that would have to be combined to do what I want to do?

         

    I have a bunch of Database resources available here, just FYI.

    http://www.cumbrowski.com/CarstenC/databasedevelopment.asp

    Thanks. I appreciate it.

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • This script is for SQL Server 2000.

    Use msdb

    Create Table #job_listing(

    row_num int identity(1,1),

    Job_Name varchar(100),

    Job_ID varchar(64),

    Schedule_Name varchar(100),

    Schedule_ID varchar(10),

    Enabled varchar(3),

    Command varchar(1000),

    Description varchar(500)

    )

    Insert #job_listing (

    Job_Name,

    Job_ID,

    Schedule_Name,

    Schedule_ID,

    Enabled,

    Command,

    Description

    )

    select

    a.name,

    a.job_id,

    b.name,

    b.schedule_id,

    Case a.enabled when 1 then 'Yes' when 0 then 'No' end as Enabled,

    Case when b.schedule_id IS NULL

    then 'Update #job_listing Set Description = ''NO SCHEDULE DEFINED'' where

    row_num = (select top 1 row_num from #job_listing where Description is

    NULL)'

    else 'Declare @schedule_description varchar(2000); exec

    sp_get_schedule_description '

    + cast(b.freq_type as varchar(15)) + ', '

    + cast(b.freq_interval as varchar(15)) + ', '

    + cast(b.freq_subday_type as varchar(15)) + ', '

    + cast(b.freq_subday_interval as varchar(15)) + ', '

    + cast(b.freq_relative_interval as varchar(15)) + ', '

    + cast(b.freq_recurrence_factor as varchar(15)) + ', '

    + cast(b.active_start_date as varchar(15)) + ', '

    + cast(b.active_end_date as varchar(15)) + ', '

    + cast(b.active_start_time as varchar(15)) + ', '

    + cast(b.active_end_time as varchar(15))

    + ' , @schedule_description = @schedule_description OUT; Update

    #job_listing set Description = @schedule_description where row_num =

    (select top 1 row_num from #job_listing where Description is NULL)' end as

    Command,

    NULL

    from sysjobs a

    Left outer join sysjobschedules b

    ON a.job_id = b.job_id

    order by a.name

    Declare @a int, @b-2 int, @cmd varchar(2000)

    Set @a = 1

    Select @b-2 = max(row_num) from #job_listing

    While @a <= @b-2

    Begin

    Select @cmd = Command from #job_listing where @a = row_num

    Exec( @cmd )

    Print @cmd

    Set @a = @a + 1

    End

    SELECT * from #job_listing

    Drop Table #job_listing

    Courtesy:

    http://www.lazydba.com

    Cheers,
    Sugeshkumar Rajendran
    SQL Server MVP
    http://sugeshkr.blogspot.com

  • If you need such comprenhesive set of features may I suggest you use SQL Server Sentry (http://www.sqlsentry.net/)


    * Noel

  • Hi Sugesh,

    Nope, that's not it. It does not consider the repititions.

    Example

    If there is only one job scheduled to run

    1) every 5 minutes,

    2) on every weekday

    3) between 1:30pm and 2:00pm

    You would get the following results

    1) start date/time 7/7/2007 12:00pm, end date/time 7/8/2007 2:00pm

    nothing, because the 7/7/2007 and 7/8/2007 are on the weekend

    2) start date/time 7/5/2007 12:00pm, end date/time 7/5/2007 1:45pm

    7/5/2007 1:30pm

    7/5/2007 1:35pm

    7/5/2007 1:40pm

    7/5/2007 1:45pm

    3) start date/time 7/5/2007 1:45pm, end date/time 7/6/2007 3:00pm

    7/5/2007 1:45pm

    7/5/2007 1:50pm

    7/5/2007 1:55pm

    7/5/2007 2:00pm

    7/6/2007 1:30pm

    7/6/2007 1:35pm

    7/6/2007 1:40pm

    7/6/2007 1:45pm

    7/6/2007 1:50pm

    7/6/2007 1:55pm

    7/6/2007 2:00pm

    Now SQL has a lot more configuration options for the scheduler.

    Autom. when SQL starts

    freq_type=64

     

     

     

    Starts when CPU idle

    freq_type=128

     

     

     

    One Time          On Date mm/dd/yyyy at time: hh:mm:ss am/pm

    freq_type=1

     

     

     

    Recurring

     

    -----------------------------------------------

     

    Occurs

     

                Daily

    freq_type=4

                            Every x day(s)

    freq_interval=x

     

     

     

                Weekly

    freq_type=8

                            Every x week(s) on

    freq_recurrence_factor=x

                            Mo [ ], Tu [ ], We [ ], Th [ ],

                            Fr [ ], Sa [ ], Su [ ],

                           

    1 = Sunday, 2 = Monday, 4 = Tuesday, 8 = Wednesday, 16 = Thursday, 32 = Friday, 64 = Saturday. Examples: Su  and Mo enabled = 3  (1 (Su) + 2 (Mo)), Mo, We and Fr enabled = 42 (2 (Mo) + 8 (We) + 32 (Fr))

     

                Monthly

     

                            Day X of every Y month(s)

    freq_type=16

     

     

    freq_interval=X

                           

    freq_recurrence_factor=Y

                            or

     

     

     

     

                            The 1st,2nd,3rd,4th,LAST WEEKDAY

    freq_type=32

     of every Y month(s)

    -----------------------------------------------

     

    freq_relative_interval=1,2,4 (3rd),8 (4th),16(last)

     

     

    freq_interval= 1=Su,2=Mo,3=Tu,4=We,5=Th,6=Fr,7=Sa,

    8=Day,9=Weekday,10=Weekend day

     

     

    freq_recurrence_factor=Y

     

     

     

     

     

     

    Occurs Once at   hh:mm:ss AM/PM

    freq_subday_type=0x1

     or

     

    Occurs Every  X Hours/Minutes              

    Starting: hh:mm:ss A/PM

    freq_subday_type=0x4 (minutes) or 0x8 (hours)

                                                                Ending: hh:mm:ss A/PM

    freq_subday_interval=X

     

     

    active_start_time

     

     

    active_end_time

    -----------------------------------------------

     

     

     

     

    Start Date mm/dd/yyy                End Date  mm/dd/yyyy

    active_start_date

                                                    or

    active_end_date

                                                    No End Date

    active_end_date=99991231

     

    And don't forget that you can have more than one schedule record for any single job, including no-schedule record (which would not interest me).

     

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • Crap, it ate the comment....

    Hi Noel

    SQL Sentry is fine and they did what I need, but there is no T-SQL Code, it's part of their windows software. I need it as SQL script to be able to use it for the various purposes of mine, some are unique, but some are not, like the mentioned.

    I am surprised that nobody wrote a script over the years yet, at least none that can be easily found. I was searching for something that does that like crazy. It is not a SQL 2005 specific thing, but for SQL 2000 as well.

     

     

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • mmh... same silence as everywhere else.

    I can't believe that I am the only one who requires something like that.

    There does not exist any t-sql script / stored procedure that does this?

    I offer $25 to anybody who can point me to a stored procedure that does the described (it does not have to return exactly the table columns I mentioned, I can add that code myself, but it should do the determination of the individual job executions for any specified date/time range).

    I offer $100 to anybody who writes and publishes a stored procedure that does the described. Please post it here at SQLServerCentral.com, accessible to anybody (public and for free) and I will send you the money (check or paypal).

    SQL 2000 compatible would be preferred, but SQL 2005 code that can be altered to query a linked SQL 2000 server using DTC will work too (the production server in use where I need this is SQL 2000)

    Thanks

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • Generous but I'm curious... why would you pay someone $100 to write code and post it on a public/free forum?  Hate to look a gift horse in the mouth, but what do you get out of it?

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff,

    I don't mind your question, which is valid and deserves answers. Here we go:

    1. The next poor guy might finds it quickly and does not have to spend the time I did in disbelieve that with all the thousands of scripts out there, none exists that seems to address this problem.

    2. There is nothing "genius" about it or a reason to hide it from people.

    3. Furthermore is it only right to have it published on the site where the forum resides and the request was made.

    4. I don't think that it would be cool to offer a bounty, get what I need and then run with it, without sharing it.

    5. Chances are that this thread will come up in search engines one day if somebody looks for the same solution. Speaking from personal experience. I hate forum threads that start with somebody asking exactly the same question I have without resulting in an answer and only leaving me with the knowledge that I am not alone in my quest for an answer.

    6. If everybody would do it the way I do it, I will benefit from it as well, because I will actually find an answer to my question and will be thankful to the person who was going through the length of getting it.

    7. Don't expect from others that you won't do yourself.

    8. $100 tax and fee free is a lot of money for some guys out there. It is not much for me, if broken down to a hourly rate and what one hour of my time is worth to me.

    I hope this makes sense and If this attempt results in an answer to my problem, I will only be mad that I didn't do it this way in the first place.

    Eight good reasons in my opinion. Don't you think so too?

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • Carsten,

    Thanks for the detailed feedback.  Hard to believe that someone has that particular attitude.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • great, it ate another comment of mine. I guess doing a post without prior preview does not work. Everything I entered was gone, except for the first few words.

    Jeff, well, the short version of my intended response is that it is not very hard to have this kind of attitude, because it does have its very own egoistic benefits, but without the negative side effects. What goes around, comes around.

    Cheers!

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • There's some sort of nasy ol' timeout... I always do a select-all and copy before I try to post... just in case...

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Carsten,

    We have a job (which I cannot post because I did not write it) which monitors our job execution times.  It tracks the average run time of each job in a table and then lets us know if a job runs longer than it should be running.  The advice I can give you is this. 

    Create a table that tracks the job_ID, the job_state and the last / next run date & time.  You should be able to break down the Last_run_time (with some conversions) to see how long the job ran when it last ran.  Then, the next time the job runs, store it in a different field or record.  Compare the two to see the difference in run times.  You can use this method to find all your values (min, max and average), especially if you track this information in separate records each time.

    You've already got the tables you need.  BOL should be able to help you with the actual conversions.  Sorry I can't post any code, but like I said, it belongs to someone else and I don't have his permission to share it.

    Brandie Tarvin, MCITP Database AdministratorLiveJournal Blog: http://brandietarvin.livejournal.com/[/url]On LinkedIn!, Google+, and Twitter.Freelance Writer: ShadowrunLatchkeys: Nevermore, Latchkeys: The Bootleg War, and Latchkeys: Roscoes in the Night are now available on Nook and Kindle.

  • I think the "hard part" isn't coming up with the fine code you guys already did, Brandi... the bugger is coming up with all future dates and times for a given future date range...

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Hi Brandie,

    I am not sure if that would work.  The jobs I want to look at already write into a log file, if they run. The jobs create new jobs depending on the available databases on a number of servers. Each of those jobs also creates an entry in a log table.

    The MSDB database exceeds 2.5 GB every other week because of the volume.

    The problem is that some of the jobs created by the jobs don't seem to run from time to time without an error (at least none we capture). I wanted to determine which jobs should have been created and executed in a given time frame to check against the logs if entries are missing.

    In a nutshell: The script would allow me to calculate all the occurrences that should have happened to then compare it to what actually did happen. It would also allow me to do predictions about the future executions and alerts could be triggered, if they do not happen.

    This initial problem got me into the general problem, which I published here. The general problem helps solving a number of other problems as well and the reason why I am surprised that there does not seem to be a public solution available for it yet.

    Does this make sense? Thanks for your offer though. I appreciate it.

    Jeff: "the bugger is coming up with all future dates and times for a given future date range..."

    You are right on the money (in parts). My example is a bit special due to the high volume. I can't add another tracking to what is already there, because that would overload the server. I want to do the analysis on a different box with past data.

    p.s. I keep in mind the idea with saving the post in the clipboard. I usually do that with blogs. I never thought it to be necessary with online forums hehe.

    Cheers!

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

  • Somebody posted a solution for this problem (source code of a very long UDF) at a different SQL Server forum at

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=96424

    So, if you have the same issue and found this thread describing it perfectly, here is now also an answer and solution for it as well. 🙂

    Carsten Cumbrowski
    MS SQL Server Resources Meta Search Engine
    SQLHunt.com[/url]

Viewing 15 posts - 1 through 15 (of 18 total)

You must be logged in to reply to this topic. Login to reply