This is a bit long and clunky, but it gives some quick insight into the SQL Agent jobs that run on a server.
-- Summary of SQL Agent jobs
-- job name, typical start time, average duration, average job runs per day, last run date/time, enabled
USE msdb
DECLARE @job_user sysname
SET @job_user = '[domain]\[account]'
SET @job_user = NULL
SELECT
src2.name AS job_name,
-- -- if a job runs more than once per day, its average start time tends to cluster near mid-day
-- -- and become a useless measure, so we'll use NULL for these cases
CASE WHEN src5.avg_runs_per_day = 1 THEN
RIGHT('00' + CAST(((AVG(src2.start_time_in_seconds)/60)/60) % 60 AS VARCHAR), 2) + ':' +
RIGHT('00' + CAST((AVG(src2.start_time_in_seconds)/60) % 60 AS VARCHAR), 2) + ':' +
RIGHT('00' + CAST(AVG(src2.start_time_in_seconds) % 60 AS VARCHAR), 2)
ELSE
NULL
END AS typical_start_time,
RIGHT('00' + CAST(((AVG(src2.duration_in_seconds)/60)/60) % 60 AS VARCHAR), 2) + ':' +
RIGHT('00' + CAST((AVG(src2.duration_in_seconds)/60) % 60 AS VARCHAR), 2) + ':' +
RIGHT('00' + CAST(AVG(src2.duration_in_seconds) % 60 AS VARCHAR), 2) AS avg_duration,
src5.avg_runs_per_day,
CONVERT(VARCHAR, MAX(src2.run_date_time), 120) AS last_run_date_time,
src6.enabled
FROM
-- -- get our average start time and average duration by job name
(
SELECT
CAST(SUBSTRING(convert(VARCHAR, run_date_time, 121), 12, 2) AS INT) * 60 * 60 +
CAST(SUBSTRING(convert(VARCHAR, run_date_time, 121), 15, 2) AS INT) * 60 +
CAST(SUBSTRING(convert(VARCHAR, run_date_time, 121), 18, 2) AS INT) AS start_time_in_seconds,
CAST(SUBSTRING(run_duration, 1, 2) AS INT) * 60 * 60 +
CAST(SUBSTRING(run_duration, 4, 2) AS INT) * 60 +
CAST(SUBSTRING(run_duration, 7, 2) AS INT) AS duration_in_seconds,
run_date_time,
name
FROM
(
SELECT
sj.NAME,
cast(
SUBSTRING(CAST(run_date AS VARCHAR), 1, 4) + '-' +
SUBSTRING(CAST(run_date AS VARCHAR), 5, 2) + '-' +
SUBSTRING(CAST(run_date AS VARCHAR), 7, 2) + ' ' +
SUBSTRING(RIGHT('00000' + CAST(run_time AS VARCHAR), 6), 1, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_time AS VARCHAR), 6), 3, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_time AS VARCHAR), 6), 5, 2)
AS DATETIME) AS run_date_time,
SUBSTRING(RIGHT('00000' + CAST(run_duration AS VARCHAR), 6), 1, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_duration AS VARCHAR), 6), 3, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_duration AS VARCHAR), 6), 5, 2)
AS run_duration
FROM
sysjobhistory AS jh
INNER JOIN sysjobs AS sj
ON jh.[job_id] = sj.[job_id]
AND jh.step_name = '(Job outcome)'
WHERE
-- -- we only want to know about jobs that were running because they were scheduled or because
-- -- they were called by another job
jh.MESSAGE LIKE 'The job succeeded. The Job was invoked by Schedule%'
OR jh.MESSAGE LIKE 'The job succeeded. The job was invoked by User ' + @job_user + '%'
OR jh.MESSAGE LIKE 'The job failed. The Job was invoked by Schedule%'
OR jh.MESSAGE LIKE 'The job failed. The job was invoked by User ' + @job_user + '%'
) AS src
) AS src2
-- -- we have average start time and average duration. now, let's get join in average runs per day by job name
INNER JOIN
(
SELECT
name AS job_name,
AVG(runs_per_day) AS avg_runs_per_day
FROM
(
SELECT
NAME,
COUNT(run_duration) AS runs_per_day
FROM
(
SELECT
sj.NAME,
cast(
SUBSTRING(CAST(run_date AS VARCHAR), 1, 4) + '-' +
SUBSTRING(CAST(run_date AS VARCHAR), 5, 2) + '-' +
SUBSTRING(CAST(run_date AS VARCHAR), 7, 2) + ' ' +
SUBSTRING(RIGHT('00000' + CAST(run_time AS VARCHAR), 6), 1, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_time AS VARCHAR), 6), 3, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_time AS VARCHAR), 6), 5, 2)
AS DATETIME) AS run_date_time,
SUBSTRING(RIGHT('00000' + CAST(run_duration AS VARCHAR), 6), 1, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_duration AS VARCHAR), 6), 3, 2) + ':' +
SUBSTRING(RIGHT('00000' + CAST(run_duration AS VARCHAR), 6), 5, 2)
AS run_duration
FROM
sysjobhistory AS jh
INNER JOIN sysjobs AS sj
ON jh.[job_id] = sj.[job_id]
AND jh.step_name = '(Job outcome)'
WHERE
-- -- we only want to know about jobs that were running because they were scheduled or because
-- -- they were called by another job
jh.MESSAGE LIKE 'The job succeeded. The Job was invoked by Schedule%'
OR jh.MESSAGE LIKE 'The job succeeded. The job was invoked by User ' + @job_user + '%'
OR jh.MESSAGE LIKE 'The job failed. The Job was invoked by Schedule%'
OR jh.MESSAGE LIKE 'The job failed. The job was invoked by User ' + @job_user + '%'
) AS src3
GROUP BY
name,
CONVERT(VARCHAR, run_date_time,112)
) AS src4
GROUP BY
NAME
) AS src5
ON src2.NAME = src5.job_name
INNER JOIN sysjobs AS src6
ON src2.NAME = src6.NAME
GROUP BY
src2.NAME,
src5.avg_runs_per_day,
src6.enabled
ORDER BY
typical_start_time DESC,
last_run_date_time ASC
1 comment:
You know, a lot of times a script similar to what you need has been posted by some kind soul on his/her blog but this one for job history (esp. average start time) was on the money for me!
Thank you very much for sharing Ken :) You inspired me to post some of my own scripts on forums!
Post a Comment