Additional table in statement with OUTER APPLY

  • I've created the below query to retrieve some information on agent jobs scheduled which works fine and returns 33 rows. I'm trying to pull the next_scheduled_run_date from sysjobactivity, but whatever I try with JOINs on the 3rd table it returns more than 200 rows now (it's pulling back all rows where the job has ran rather than just the latest run). I just need the same data as original but with the next scheduled run date included also. It's probably really straightforward but I can't see the wood for the trees at the moment.

    Use MSDB

    Go

    Select Name, [Enabled], run_date as [Last_Run_Date], Run_Status, Run_Duration, Date_Modified

    FROM sysjobs A

    OUTER APPLY (SELECT TOP 1 * FROM sysjobhistory B

    WHERE A.job_id = B.job_id

    ORDER BY B.run_date DESC) as B

    Thanks in advance

  • TheFault (8/10/2016)


    I've created the below query to retrieve some information on agent jobs scheduled which works fine and returns 33 rows. I'm trying to pull the next_scheduled_run_date from sysjobactivity, but whatever I try with JOINs on the 3rd table it returns more than 200 rows now (it's pulling back all rows where the job has ran rather than just the latest run). I just need the same data as original but with the next scheduled run date included also. It's probably really straightforward but I can't see the wood for the trees at the moment.

    Use MSDB

    Go

    Select Name, [Enabled], run_date as [Last_Run_Date], Run_Status, Run_Duration, Date_Modified

    FROM sysjobs A

    OUTER APPLY (SELECT TOP 1 * FROM sysjobhistory B

    WHERE A.job_id = B.job_id

    ORDER BY B.run_date DESC) as B

    Thanks in advance

    Seems to work OK for me, though I would suggest trying out the alternative method I show below too, for performance reasons:

    USE msdb;

    GO

    SELECT A.name

    , A.enabled

    , B.run_date AS Last_Run_Date

    , B.run_status

    , B.run_duration

    , A.date_modified

    FROM dbo.sysjobs A

    OUTER APPLY (SELECT TOP 1

    B.run_date

    , B.run_status

    , B.run_duration

    FROM dbo.sysjobhistory B

    WHERE A.job_id = B.job_id

    ORDER BY B.run_date DESC

    ) AS B;

    WITH OrderedRunDates

    AS (SELECT jh1.job_id

    , rn = ROW_NUMBER() OVER (PARTITION BY jh1.job_id ORDER BY jh1.run_date DESC)

    , jh1.run_date

    , jh1.run_status

    , jh1.run_duration

    FROM dbo.sysjobhistory jh1

    )

    SELECT A.name

    , A.enabled

    , ord.run_date AS Last_Run_Date

    , ord.run_status

    , ord.run_duration

    , A.date_modified

    FROM dbo.sysjobs A

    LEFT JOIN OrderedRunDates ord ON A.job_id = ord.job_id

    WHERE ISNULL(ord.rn,1) = 1;

    The absence of evidence is not evidence of absence.
    Martin Rees

    You can lead a horse to water, but a pencil must be lead.
    Stan Laurel

  • Phil Parkin (8/10/2016)


    TheFault (8/10/2016)


    I've created the below query to retrieve some information on agent jobs scheduled which works fine and returns 33 rows. I'm trying to pull the next_scheduled_run_date from sysjobactivity, but whatever I try with JOINs on the 3rd table it returns more than 200 rows now (it's pulling back all rows where the job has ran rather than just the latest run). I just need the same data as original but with the next scheduled run date included also. It's probably really straightforward but I can't see the wood for the trees at the moment.

    Use MSDB

    Go

    Select Name, [Enabled], run_date as [Last_Run_Date], Run_Status, Run_Duration, Date_Modified

    FROM sysjobs A

    OUTER APPLY (SELECT TOP 1 * FROM sysjobhistory B

    WHERE A.job_id = B.job_id

    ORDER BY B.run_date DESC) as B

    Thanks in advance

    Seems to work OK for me, though I would suggest trying out the alternative method I show below too, for performance reasons:

    USE msdb;

    GO

    SELECT A.name

    , A.enabled

    , B.run_date AS Last_Run_Date

    , B.run_status

    , B.run_duration

    , A.date_modified

    FROM dbo.sysjobs A

    OUTER APPLY (SELECT TOP 1

    B.run_date

    , B.run_status

    , B.run_duration

    FROM dbo.sysjobhistory B

    WHERE A.job_id = B.job_id

    ORDER BY B.run_date DESC

    ) AS B;

    WITH OrderedRunDates

    AS (SELECT jh1.job_id

    , rn = ROW_NUMBER() OVER (PARTITION BY jh1.job_id ORDER BY jh1.run_date DESC)

    , jh1.run_date

    , jh1.run_status

    , jh1.run_duration

    FROM dbo.sysjobhistory jh1

    )

    SELECT A.name

    , A.enabled

    , ord.run_date AS Last_Run_Date

    , ord.run_status

    , ord.run_duration

    , A.date_modified

    FROM dbo.sysjobs A

    LEFT JOIN OrderedRunDates ord ON A.job_id = ord.job_id

    WHERE ISNULL(ord.rn,1) = 1;

    It's not always faster Phil, but this slight variant is:

    WITH OrderedRunDates

    AS (SELECT jh1.job_id

    , rn = ROW_NUMBER() OVER (PARTITION BY jh1.job_id ORDER BY jh1.run_date DESC)

    , jh1.run_date

    , jh1.run_status

    , jh1.run_duration

    FROM dbo.sysjobhistory jh1

    )

    SELECT A.name

    , A.enabled

    , ord.run_date AS Last_Run_Date

    , ord.run_status

    , ord.run_duration

    , A.date_modified

    FROM dbo.sysjobs A

    LEFT JOIN OrderedRunDates ord ON A.job_id = ord.job_id AND ord.rn = 1;

    --WHERE ISNULL(ord.rn,1) = 1;

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Here's an option. You can follow Phil's advice for a possible improvement on performance.

    Use MSDB

    Go

    Select j.name,

    j.[enabled],

    B.run_date as [Last_Run_Date],

    b.run_status,

    b.run_duration,

    j.date_modified,

    B.next_scheduled_run_date

    FROM sysjobs j

    OUTER APPLY (SELECT TOP 1 h.*, a.next_scheduled_run_date

    FROM sysjobhistory h

    JOIN sysjobactivity a ON h.instance_id = a.job_history_id

    WHERE j.job_id = h.job_id

    ORDER BY h.run_date DESC) as B

    ORDER BY Name;

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • ChrisM@Work (8/10/2016)


    It's not always faster Phil, but this slight variant is:

    Nice tweak, Chris. I often forget this nuance.

    The absence of evidence is not evidence of absence.
    Martin Rees

    You can lead a horse to water, but a pencil must be lead.
    Stan Laurel

  • I don't see any reason to conflate the last run with the next run. Also, when you query job activity, you need to include the session_id to make sure you don't see obsolete data:

    SELECT

    j.Name AS Job_Name, j.[Enabled],

    jh.run_date as [Last_Run_Date], jh.Run_Status, jh.Run_Duration,

    j.Date_Modified, ja.next_scheduled_run_date

    FROM msdb.dbo.sysjobs j

    LEFT OUTER JOIN (

    SELECT jh2.*, ROW_NUMBER() OVER(PARTITION BY jh2.job_id ORDER BY run_date DESC) AS row_num

    FROM msdb.dbo.sysjobhistory jh2

    ) AS jh ON jh.job_id = j.job_id AND jh.row_num = 1

    LEFT OUTER JOIN msdb.dbo.sysjobactivity ja ON ja.job_id = j.job_id AND

    ja.session_id = (SELECT MAX(s.session_id) FROM msdb.dbo.syssessions s)

    /*ORDER BY Job_Name*/

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • Thanks all, I'm tested out these solutions further as they are all bringing back slightly different run durations and run statuses each.

Viewing 7 posts - 1 through 6 (of 6 total)

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