Sql agent job last run status - sql

I have N jobs with M steps in each, that could change any time(Add/delete some steps). Jobs have different schedule to run. I want a query to get last run status, job id, job name of each job. Is it right way to do this scenario by (Job outcome) ?

This is the query I use (a little tuned) to check job status. This variation will select the last job outcome for each job.
SELECT
JobName = J.name,
H.*
FROM
msdb.dbo.sysjobs AS J
CROSS APPLY (
SELECT TOP 1
JobName = J.name,
StepNumber = T.step_id,
StepName = T.step_name,
StepStatus = CASE T.run_status
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Canceled'
ELSE 'Running' END,
ExecutedAt = msdb.dbo.agent_datetime(T.run_date, T.run_time),
ExecutingHours = ((T.run_duration/10000 * 3600 + (T.run_duration/100) % 100 * 60 + T.run_duration % 100 + 31 ) / 60) / 60,
ExecutingMinutes = ((T.run_duration/10000 * 3600 + (T.run_duration/100) % 100 * 60 + T.run_duration % 100 + 31 ) / 60) % 60,
Message = T.message
FROM
msdb.dbo.sysjobhistory AS T
WHERE
T.job_id = J.job_id
ORDER BY
T.instance_id DESC) AS H
ORDER BY
J.name
If you change the TOP 1 for TOP 2, then you will also see the last step executed, aside from the job outcome.

You can not get everything in a single query and need more research. For e.g., to know Job execution information you can try the following query.
SELECT
[sJOB].[job_id] AS [JobID]
, [sJOB].[name] AS [JobName]
, CASE
WHEN [sJOBH].[run_date] IS NULL OR [sJOBH].[run_time] IS NULL THEN NULL
ELSE CAST(
CAST([sJOBH].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJOBH].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS [LastRunDateTime]
, CASE [sJOBH].[run_status]
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Canceled'
WHEN 4 THEN 'Running' -- In Progress
END AS [LastRunStatus]
, STUFF(
STUFF(RIGHT('000000' + CAST([sJOBH].[run_duration] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS [LastRunDuration (HH:MM:SS)]
, [sJOBH].[message] AS [LastRunStatusMessage]
, CASE [sJOBSCH].[NextRunDate]
WHEN 0 THEN NULL
ELSE CAST(
CAST([sJOBSCH].[NextRunDate] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJOBSCH].[NextRunTime] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS [NextRunDateTime]
FROM
[msdb].[dbo].[sysjobs] AS [sJOB]
LEFT JOIN (
SELECT
[job_id]
, MIN([next_run_date]) AS [NextRunDate]
, MIN([next_run_time]) AS [NextRunTime]
FROM [msdb].[dbo].[sysjobschedules]
GROUP BY [job_id]
) AS [sJOBSCH]
ON [sJOB].[job_id] = [sJOBSCH].[job_id]
LEFT JOIN (
SELECT
[job_id]
, [run_date]
, [run_time]
, [run_status]
, [run_duration]
, [message]
, ROW_NUMBER() OVER (
PARTITION BY [job_id]
ORDER BY [run_date] DESC, [run_time] DESC
) AS RowNumber
FROM [msdb].[dbo].[sysjobhistory]
WHERE [step_id] = 0
) AS [sJOBH]
ON [sJOB].[job_id] = [sJOBH].[job_id]
AND [sJOBH].[RowNumber] = 1
ORDER BY [JobName]
You can get and learn in details - Here and Here

Related

How to create a 2nd temp table in SQL

I have such a situation. I basically need to put my whole code into a second temp table(?) to be able to select from it. The code inside works just fine I just cannot understand how to basically create a bigger temp table that will absorb the first one and the previous select and later allow select one more time.
This is what I have right now
WITH t AS
( Select
p.[PDITM#], l.SGDWHS, p.PDCHN, p.PDWEDT, Sum(p.PDQSLD) AS 'Sum',
case when p.PDCHN = 'DH' then p.PDQSLD else 0 end as DHSLD,
case when p.PDCHN = 'WM' then p.PDQSLD else 0 end as WMSLD,
case when p.PDCHN = 'MJ' then p.PDQSLD else 0 end as MJSLD,
case when p.PDCHN = 'BJ' then p.PDQSLD else 0 end as BJSLD
FROM [Repit].[LEVYDTA].[POSDTLM] p
LEFT OUTER JOIN [Repit].[LEVYDTA].[LDSSGEN] l
ON p.[PDAGY]=l.[SGAGY] AND p.[PDCHN] = l.[SGCHN] AND p.[PDSTR] = l.[SGSTR]
WHERE p.[PDQSLD] > 0 AND p.[PDAGY] != 15
AND l.[SGDWHS] IN (01, 21, 30, 40, 02)
AND CONVERT(DATE, CONVERT(CHAR(8), p.PDWEDT )) = cast(DATEADD(dd, DATEPART(DW,GETDATE())*-1, GETDATE()) as date)
GROUP BY p.[PDITM#], l.[SGDWHS], p.[PDCHN], p.[PDWEDT], p.[PDQSLD]
)
select t.[PDITM#] as [PDITM#],
t.SGDWHS as [SGDWHS],
SUM(t.Sum) as [PDQSLD],
SUM(t.DHSLD) AS [DHSLD],
SUM(t.WMSLD) AS [WMSLD],
SUM(t.MJSLD) AS [MJSLD],
SUM(t.BJSLD) AS [BJSLD],
SUM(t.Sum) - (SUM(t.DHSLD) + SUM(t.WMSLD) + SUM(t.MJSLD) + SUM(t.BJSLD)) as OTHRSLD
from t
GROUP BY t.PDITM#, t.SGDWHS
ORDER BY t.PDITM#, t.SGDWHS
I need to select such fields from the upper table
SELECT t.PDITM#, t.SGDWHS,
CAST((t.DHSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'DHPCT',
CAST((t.WMSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'WMPCT',
CAST((t.MJSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'MJPCT',
CAST((t.BJSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'BJPCT',
CAST(((t.Sum - ( t.DHSLD + t.WMSLD + t.MJSLD + t.BJSLD))/t.Sum) * 100 as DECIMAL (18,2)) AS 'OTHRPCT'
FROM second temp table
I will appreciate if someone can let me know how it may be possible. I have spent time trying to figure it out by myself, but there is not much info when you need to make multiple temp tables and selecting them.
If you're using MSSQL, this might be what you're trying to do?
-- Drop temp table if already present
DROP TABLE IF EXISTS #temp_main
SELECT
p.[PDITM#]
, l.SGDWHS
, p.PDCHN
, p.PDWEDT
, SUM(p.PDQSLD) AS [Sum_PDQSLD]
, case when p.PDCHN = 'DH' then p.PDQSLD else 0 end as [DHSLD]
, case when p.PDCHN = 'WM' then p.PDQSLD else 0 end as [WMSLD]
, case when p.PDCHN = 'MJ' then p.PDQSLD else 0 end as [MJSLD]
, case when p.PDCHN = 'BJ' then p.PDQSLD else 0 end as [BJSLD]
-- Select data into temp table.
INTO #temp_main
FROM [Repit].[LEVYDTA].[POSDTLM] AS p
LEFT JOIN [Repit].[LEVYDTA].[LDSSGEN] AS l
ON p.[PDAGY]=l.[SGAGY] AND p.[PDCHN] = l.[SGCHN] AND p.[PDSTR] = l.[SGSTR]
WHERE p.[PDQSLD] > 0 AND p.[PDAGY] != 15 AND l.[SGDWHS] IN (01, 21, 30, 40, 02)
AND CONVERT(DATE, CONVERT(CHAR(8), p.PDWEDT)) = cast(DATEADD(dd, DATEPART(DW,GETDATE())*-1, GETDATE()) as date)
GROUP BY
p.[PDITM#]
, l.[SGDWHS]
, p.[PDCHN]
, p.[PDWEDT]
, p.[PDQSLD]
-- Table 1
SELECT
t.[PDITM#]
, t.SGDWHS
, SUM(t.Sum_PDQSLD) as [PDQSLD]
, SUM(t.DHSLD) AS [DHSLD]
, SUM(t.WMSLD) AS [WMSLD]
, SUM(t.MJSLD) AS [MJSLD]
, SUM(t.BJSLD) AS [BJSLD]
, SUM(t.Sum_PDQSLD) - (SUM(t.DHSLD) + SUM(t.WMSLD) + SUM(t.MJSLD) + SUM(t.BJSLD)) as [OTHRSLD]
from #temp_main AS t -- Temp table
GROUP BY t.[PDITM#], t.SGDWHS
ORDER BY t.[PDITM#], t.SGDWHS
-- Table 2
SELECT
t.[PDITM#]
, t.SGDWHS
, CAST((t.DHSLD/t2.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [DHPCT]
, CAST((t.WMSLD/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [WMPCT]
, CAST((t.MJSLD/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [MJPCT]
, CAST((t.BJSLD/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [BJPCT]
, CAST(((t.Sum_PDQSLD - (t.DHSLD + t.WMSLD + t.MJSLD + t.BJSLD))/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [OTHRPCT]
FROM #temp_main AS t -- Temp table
ORDER BY t.[PDITM#], t.SGDWHS
-- Drop table once complete.
DROP TABLE #table_main

Getting execution status of SQL Server Agent Job in SQL Server 2012

I am trying to get currently executing job status in SQL Server 2012. I have tried using sp_help_job procedure to get it using execution_status as argument also used run_status/status but it is not returning any value.
Please help
SELECT
[sJOB].[job_id] AS [JobID]
, [sJOB].[name] AS [JobName]
, CASE
WHEN [sJOBH].[run_date] IS NULL OR [sJOBH].[run_time] IS NULL THEN NULL
ELSE CAST(
CAST([sJOBH].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJOBH].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS [LastRunDateTime]
, CASE [sJOBH].[run_status]
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Canceled'
WHEN 4 THEN 'Running' -- In Progress
END AS [LastRunStatus]
, STUFF(
STUFF(RIGHT('000000' + CAST([sJOBH].[run_duration] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS [LastRunDuration (HH:MM:SS)]
, [sJOBH].[message] AS [LastRunStatusMessage]
, CASE [sJOBSCH].[NextRunDate]
WHEN 0 THEN NULL
ELSE CAST(
CAST([sJOBSCH].[NextRunDate] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJOBSCH].[NextRunTime] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS [NextRunDateTime]
FROM
[msdb].[dbo].[sysjobs] AS [sJOB]
LEFT JOIN (
SELECT
[job_id]
, MIN([next_run_date]) AS [NextRunDate]
, MIN([next_run_time]) AS [NextRunTime]
FROM [msdb].[dbo].[sysjobschedules]
GROUP BY [job_id]
) AS [sJOBSCH]
ON [sJOB].[job_id] = [sJOBSCH].[job_id]
LEFT JOIN (
SELECT
[job_id]
, [run_date]
, [run_time]
, [run_status]
, [run_duration]
, [message]
, ROW_NUMBER() OVER (
PARTITION BY [job_id]
ORDER BY [run_date] DESC, [run_time] DESC
) AS RowNumber
FROM [msdb].[dbo].[sysjobhistory]
WHERE [step_id] = 0
) AS [sJOBH]
ON [sJOB].[job_id] = [sJOBH].[job_id]
AND [sJOBH].[RowNumber] = 1
AND [Jobname] = #Jobname
ORDER BY [JobName]

SQL Server Agent - Unique ID for Each Job Execution

I have this query that provides a lot of useful info for my scheduled jobs but there is one thing I am still missing. I am trying to locate a unique ID for every job execution, not the instance or schedule ID. Does this exist, and of so how would I join it to the current tables I'm using? Any assistance is appreciated.
Thanks!
Edit: I know I can create a unique ID for jobs that run once per day but most of the jobs run multiple time per day. Some run every 2 minutes.
SELECT h.instance_id
, j.job_id
,j.name AS JobName
,CASE
WHEN h.step_name = '(Job outcome)'
THEN 'Job Run Time'
ELSE h.step_name
END AS StepName
,h.step_id
,CAST(STR(h.run_date, 8, 0) AS DATETIME) + CAST(STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS DATETIME) AS StartDatetime
,DATEADD(SECOND, ((h.run_duration / 1000000 * 86400 + (h.run_duration - h.run_duration / 1000000 * 1000000) / 10000 * 3600) + (h.run_duration - h.run_duration / 10000 * 10000) / 100 * 60) + (h.run_duration - h.run_duration / 100 * 100), CAST(STR(h.run_date, 8, 0) AS DATETIME) + CAST(STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS DATETIME)) AS EndDatetime
,CASE
WHEN STUFF(STUFF(REPLACE(STR(h.run_duration, 6, 0), ' ', '0'), 3, 0, ':'), 6, 0, ':') > '23:59:00'
THEN '23:59:00'
ELSE STUFF(STUFF(REPLACE(STR(h.run_duration, 6, 0), ' ', '0'), 3, 0, ':'), 6, 0, ':')
END AS run_duration_formatted
,((h.run_duration / 1000000 * 86400 + (h.run_duration - h.run_duration / 1000000 * 1000000) / 10000 * 3600) + (h.run_duration - h.run_duration / 10000 * 10000) / 100 * 60) + (h.run_duration - h.run_duration / 100 * 100) AS RunDurationInSeconds
,CASE h.run_status
WHEN 0
THEN 'Failed'
WHEN 1
THEN 'Succeded'
WHEN 2
THEN 'Retry'
WHEN 3
THEN 'Cancelled'
WHEN 4
THEN 'In Progress'
END AS ExecutionStatus
FROM msdb.dbo.sysjobhistory AS h
INNER JOIN msdb.dbo.sysjobs AS j ON j.job_id = h.job_id
LEFT JOIN [msdb].[dbo].[sysjobactivity] A ON A.job_id = h.job_id
WHERE (j.enabled = 1)
AND A.session_id = 1053
AND (CAST(STR(h.run_date, 8, 0) AS DATETIME) + CAST(STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS DATETIME) >= DATEADD(dd, - 1, CAST(GETDATE() AS DATE)))
Order by instance_id
Maybe use with dense_rank() and using distinct?
SELECT distinct h.instance_id
, dense_rank() over (order by j.job_id, h.run_date, h.run_time)
, j.job_id
,j.name AS JobName
,CASE
WHEN h.step_name = '(Job outcome)'
THEN 'Job Run Time'
ELSE h.step_name
END AS StepName
,h.step_id
,CAST(STR(h.run_date, 8, 0) AS DATETIME) + CAST(STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS DATETIME) AS StartDatetime
,DATEADD(SECOND, ((h.run_duration / 1000000 * 86400 + (h.run_duration - h.run_duration / 1000000 * 1000000) / 10000 * 3600) + (h.run_duration - h.run_duration / 10000 * 10000) / 100 * 60) + (h.run_duration - h.run_duration / 100 * 100), CAST(STR(h.run_date, 8, 0) AS DATETIME) + CAST(STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS DATETIME)) AS EndDatetime
,CASE
WHEN STUFF(STUFF(REPLACE(STR(h.run_duration, 6, 0), ' ', '0'), 3, 0, ':'), 6, 0, ':') > '23:59:00'
THEN '23:59:00'
ELSE STUFF(STUFF(REPLACE(STR(h.run_duration, 6, 0), ' ', '0'), 3, 0, ':'), 6, 0, ':')
END AS run_duration_formatted
,((h.run_duration / 1000000 * 86400 + (h.run_duration - h.run_duration / 1000000 * 1000000) / 10000 * 3600) + (h.run_duration - h.run_duration / 10000 * 10000) / 100 * 60) + (h.run_duration - h.run_duration / 100 * 100) AS RunDurationInSeconds
,CASE h.run_status
WHEN 0
THEN 'Failed'
WHEN 1
THEN 'Succeded'
WHEN 2
THEN 'Retry'
WHEN 3
THEN 'Cancelled'
WHEN 4
THEN 'In Progress'
END AS ExecutionStatus
FROM msdb.dbo.sysjobhistory AS h
INNER JOIN msdb.dbo.sysjobs AS j ON j.job_id = h.job_id
LEFT JOIN [msdb].[dbo].[sysjobactivity] A ON A.job_id = h.job_id
WHERE (j.enabled = 1)
--AND A.session_id = 1053
AND (CAST(STR(h.run_date, 8, 0) AS DATETIME) + CAST(STUFF(STUFF(RIGHT('000000' + CAST(h.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS DATETIME) >= DATEADD(dd, - 1, CAST(GETDATE() AS DATE)))
Order by j.job_id, instance_id
Edit: The table I used in this query is populated every 5 minutes with the data from the first query I posted.
OK, I couldn't find a unique ID for each schedule execution so I had to rethink what I could do. The query is below.
This solved my problem. I have a Google chart embedded in SharePoint that lists the jobs and the run times. Each bar represents how long the job took to run. Prior to this solution the chart only showed a failed status if the last step failed. Now with this incorporated I can see if any step failed withing each job execution. This is fantastic! In the image below you can see the red executions had a step failure within the job.
SELECT D.[instance_id]
,[JobName]
,[StepName]
,[step_id]
,[Run_Date]
,[StartDatetime]
,[StartTime]
,[EndDatetime]
,[End_Time]
,[Run_Duration_Formatted]
,[RunDurationInSeconds]
,MAX(CASE WHEN C.ExecutionStatus IS NULL THEN D.[ExecutionStatus] ELSE C.ExecutionStatus END) AS ExecutionStatus
FROM [STG_EDW].[dbo].[Job_Runs_FINAL] AS D
LEFT JOIN
(
SELECT Step0.Instance_ID
,'Failed' AS ExecutionStatus
FROM(
SELECT [instance_id]
,[JobName]
,[StartDatetime]
,[EndDatetime]
FROM [My Table]
WHERE step_id = 0) AS Step0
INNER JOIN(
SELECT Instance_ID, JobName, [StartDatetime], [EndDatetime]
FROM [My Table]
WHERE ExecutionStatus = 'Failed') AS B ON Step0.JobName = B.JobName AND B.StartDatetime >= Step0.StartDatetime AND B.EndDatetime <= Step0.EndDatetime
) AS C ON D.instance_id = C.instance_id
Group By D.[instance_id]
,[JobName]
,[StepName]
,[step_id]
,[Run_Date]
,[StartDatetime]
,[StartTime]
,[EndDatetime]
,[End_Time]
,[Run_Duration_Formatted]
,[RunDurationInSeconds]

SQL - How to find currently running job steps through TSQL

I am writing a query to find currently running job in SQL (I know we can view it in Job Active Monitor, but I've a need to do in TSQL). Though I can query sysjobactivity table to find currently running job, it's nowhere telling what job step is running (because my job might have more than 1 step).
Query I used:
SELECT s.name AS [JOB_NAME],
'' AS [STEP_ID],
'' AS STEP_NAME,
'Processing' AS STATUS,
sja.run_requested_date AS START_TIME,
null AS END_DATE,
convert(varchar, (getdate() - sja.run_requested_date), 8) AS Duration
FROM sysjobactivity sja, sysjobs s
WHERE sja.job_id = s.job_id
AND sja.run_requested_date > getdate() - 1
AND sja.stop_execution_date IS NULL
Please help me finding the step ID & Step name in which the job is currently progressing.
I think below script help to get SQL Jobs with current execution step, try this
msdb.dbo.sp_help_job #execution_status = 1
DECLARE #StepCount INT
SELECT #StepCount = COUNT(1)
FROM msdb.dbo.sysjobsteps
WHERE job_id = '0523333-5C24-1526-8391-AA84749345666' --JobID
SELECT
[JobName]
,[JobStepID]
,[JobStepName]
,[JobStepStatus]
,[RunDateTime]
,[RunDuration]
FROM
(
SELECT
j.[name] AS [JobName]
,Jh.[step_id] AS [JobStepID]
,jh.[step_name] AS [JobStepName]
,CASE
WHEN jh.[run_status] = 0 THEN 'Failed'
WHEN jh.[run_status] = 1 THEN 'Succeeded'
WHEN jh.[run_status] = 2 THEN 'Retry (step only)'
WHEN jh.[run_status] = 3 THEN 'Canceled'
WHEN jh.[run_status] = 4 THEN 'In-progress message'
WHEN jh.[run_status] = 5 THEN 'Unknown'
ELSE 'N/A'
END AS [JobStepStatus]
,msdb.dbo.agent_datetime(run_date, run_time) AS [RunDateTime]
,CAST(jh.[run_duration]/10000 AS VARCHAR) + ':' + CAST(jh.[run_duration]/100%100 AS VARCHAR) + ':' + CAST(jh.[run_duration]%100 AS VARCHAR) AS [RunDuration]
,ROW_NUMBER() OVER
(
PARTITION BY jh.[run_date]
ORDER BY jh.[run_date] DESC, jh.[run_time] DESC
) AS [RowNumber]
FROM
msdb.[dbo].[sysjobhistory] jh
INNER JOIN msdb.[dbo].[sysjobs] j
ON jh.[job_id] = j.[job_id]
WHERE
j.[name] = 'ProcessCubes' --Job Name
AND jh.[step_id] > 0
AND CAST(RTRIM(run_date) AS DATE) = CAST(GETDATE() AS DATE) --Current Date
) A
WHERE
[RowNumber] <= #StepCount
AND [JobStepStatus] = 'Failed'
Try this:
SELECT distinct
cast([sJOB].[job_id] as varchar(max)) AS execution_id
, [sJSTP].[step_name] AS executable_name
, [sJOB].[name] AS package_name
, CASE [sJSTP].[run_date]
WHEN 0 THEN NULL
ELSE
CAST(
CAST([sJSTP].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJSTP].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS start_time,
dateadd(ss, run_duration, CASE [sJSTP].[run_date]
WHEN 0 THEN NULL
ELSE
CAST(
CAST([sJSTP].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJSTP].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END) end_time
-- , [sJSTP].[run_duration] [looptijd in minuten]
, CASE [sJSTP].[run_status]
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Success'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Cancelled'
WHEN 5 THEN 'Unknown'
END AS execution_result_description
FROM
[msdb].[dbo].[sysjobhistory] AS [sJSTP]
INNER JOIN [msdb].[dbo].[sysjobs] AS [sJOB]
ON [sJSTP].[job_id] = [sJOB].[job_id]
inner join [msdb].[dbo].[sysjobsteps] steps
ON [sJSTP].[job_id] = [steps].[job_id]
where [sJSTP].[run_date] <> 0
and CASE [sJSTP].[run_date]
WHEN 0 THEN NULL
ELSE
CAST(
CAST([sJSTP].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJSTP].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END between dateadd(hh, -20, getdate()) and getdate()
and [sJSTP].[step_name] not in ('(Job outcome)')
order by start_time desc
Additionally I use this query to see step result from a running SSIS job. However, this only shows you the finished steps, not the running ones. I still have to find an SQL to see the currently running step and merge it with this one.
select distinct
cast(e.execution_id as varchar(max)),
e.executable_name,
e.package_name,
CONVERT(datetime, es.start_time) AS start_time
, CONVERT(datetime, es.end_time) AS end_time
, datediff(mi, es.start_time, es.end_time) [running time]
, case es.execution_result
when 0 then 'Success'
when 1 then 'Failed'
when 2 then 'Completion'
when 3 then 'Cancelled'
else cast(es.execution_result as varchar(max)) end as execution_result_description
from ssisdb.catalog.executables e
left join ssisdb.catalog.executable_statistics es
on e.executable_id = es.executable_id
and e.execution_id = es.execution_id
order by 6 desc

How to get the last run job details in SQL

How to get the last run job details in SQL Server Agent using SQL including the step details only for the last run job (not the job outcome) as i want to display this in an application
Please help been stuck on this for ages
This is the code I have been using below, this brings back all steps for all Jobs in the Job History,
However, I just want to see the steps from the last run job
thanks
USE msdb
Go
SELECT j.name JobName,h.step_name StepName,
CONVERT(CHAR(10), CAST(STR(h.run_date,8, 0) AS dateTIME), 111) RunDate,
STUFF(STUFF(RIGHT('000000' + CAST ( h.run_time AS VARCHAR(6 ) ) ,6),5,0,':'),3,0,':') RunTime,
h.run_duration StepDuration,
case h.run_status when 0 then 'Failed'
when 1 then 'Succeeded'
when 2 then 'Retry'
when 3 then 'Cancelled'
when 4 then 'In Progress'
end as ExecutionStatus,
h.message MessageGenerated
FROM sysjobhistory h
inner join sysjobs j
ON j.job_id = h.job_id
LEFT JOIN (
SELECT
[job_id]
, [run_date]
, [run_time]
, [run_status]
, [run_duration]
, [message]
, ROW_NUMBER() OVER (
PARTITION BY [job_id]
ORDER BY [run_date] DESC, [run_time] DESC
) AS RowNumber
FROM [msdb].[dbo].[sysjobhistory]
WHERE [step_id] = 0
) AS [sJOBH]
ON j.[job_id] = [sJOBH].[job_id]
AND [sJOBH].[RowNumber] = 1
where j.job_id = 'F04E5D3B-C873-448A-805C-C6309A92DAEC'
ORDER BY j.name, h.run_date, h.run_time desc
GO
Hopefully this helps,
Additional join to msdb.dbo.sysjobactivity shows you the start/end time at a job level. Using this range you can specify to only show you the job steps for the most recent run.
DECLARE #job_id UNIQUEIDENTIFIER
,#job_name VARCHAR(256)
SET #job_id = 'DF4C9555-5B24-4649-97CE-5708C53F762C'
SET #job_name = 'syspolicy_purge_history'
--search for job_id if none was provided
SELECT #job_id = COALESCE(#job_id,job_id)
FROM msdb.dbo.sysjobs
WHERE name = #job_name
SELECT t2.instance_id
,t1.name as JobName
,t2.step_id as StepID
,t2.step_name as StepName
,CONVERT(CHAR(10), CAST(STR(t2.run_date,8, 0) AS DATETIME), 111) as RunDate
,STUFF(STUFF(RIGHT('000000' + CAST ( t2.run_time AS VARCHAR(6 ) ) ,6),5,0,':'),3,0,':') as RunTime
,t2.run_duration
,CASE t2.run_status WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Cancelled'
WHEN 4 THEN 'In Progress'
END as ExecutionStatus
,t2.message as MessageGenerated
FROM msdb.dbo.sysjobs t1
JOIN msdb.dbo.sysjobhistory t2
ON t1.job_id = t2.job_id
--Join to pull most recent job activity per job, not job step
JOIN (
SELECT TOP 1
t1.job_id
,t1.start_execution_date
,t1.stop_execution_date
FROM msdb.dbo.sysjobactivity t1
--If no job_id detected, return last run job
WHERE t1.job_id = COALESCE(#job_id,t1.job_id)
ORDER
BY last_executed_step_date DESC
) t3
--Filter on the most recent job_id
ON t1.job_id = t3.job_Id
--Filter out job steps that do not fall between start_execution_date and stop_execution_date
AND CONVERT(DATETIME, CONVERT(CHAR(8), t2.run_date, 112) + ' '
+ STUFF(STUFF(RIGHT('000000' + CONVERT(VARCHAR(8), t2.run_time), 6), 5, 0, ':'), 3, 0, ':'), 121)
BETWEEN t3.start_execution_date AND t3.stop_execution_date
Edit: Added two parameters to the top, #job_id and #job_name. If #job_id is not provided, first it'll attempt to determine the job_id of the #job_name provided, and return the last run job is no values are provided.