SQL Scheduled job query, duration of last runs? - sql-server

Previously used this SQL Agent Jobs, how to document to get information about all SQL Scheduled jobs.
How can I find out the duration of the last run for each job? I need seconds, minutes, and hours (hopefully not, but I'm afraid).
Can anyone give some insight into how I could query this?

Assuming you're not going to have any jobs that run longer than 999 hours, this should give you a good starting point:
SELECT
j.name,
h.run_status,
durationHHMMSS = STUFF(STUFF(REPLACE(STR(h.run_duration,7,0),
' ','0'),4,0,':'),7,0,':'),
[start_date] = CONVERT(DATETIME, RTRIM(run_date) + ' '
+ STUFF(STUFF(REPLACE(STR(RTRIM(h.run_time),6,0),
' ','0'),3,0,':'),6,0,':'))
FROM
msdb.dbo.sysjobs AS j
INNER JOIN
(
SELECT job_id, instance_id = MAX(instance_id)
FROM msdb.dbo.sysjobhistory
GROUP BY job_id
) AS l
ON j.job_id = l.job_id
INNER JOIN
msdb.dbo.sysjobhistory AS h
ON h.job_id = l.job_id
AND h.instance_id = l.instance_id
ORDER BY
CONVERT(INT, h.run_duration) DESC,
[start_date] DESC;

Aaron, I've made some tweaks to your script, which include the next scheduled run time (start date is the initial start date of the schedule, not necessarily the next start date for the job), and some various other checks. Thanks for the framework though; very helpful starting point indeed!
I also took some logic from an oldie but goodie (here).
USE msdb
Go
SELECT j.Name AS 'Job Name',
'"' + NULLIF(j.Description, 'No description available.') + '"' AS 'Description',
SUSER_SNAME(j.owner_sid) AS 'Job Owner',
(SELECT COUNT(step_id) FROM dbo.sysjobsteps WHERE job_id = j.job_id) AS 'Number of Steps',
(SELECT COUNT(step_id) FROM dbo.sysjobsteps WHERE job_id = j.job_id AND command LIKE '%xp_cmdshell%') AS 'has_xpcmdshell',
(SELECT COUNT(step_id) FROM dbo.sysjobsteps WHERE job_id = j.job_id AND command LIKE '%msdb%job%') AS 'has_jobstartstopupdate',
(SELECT COUNT(step_id) FROM dbo.sysjobsteps WHERE job_id = j.job_id AND command LIKE '%ftp%') AS 'has_ftp',
'Job Enabled' = CASE j.Enabled
WHEN 1 THEN 'Yes'
WHEN 0 THEN 'No'
END,
'Frequency' = CASE s.freq_type
WHEN 1 THEN 'Once'
WHEN 4 THEN 'Daily'
WHEN 8 THEN 'Weekly'
WHEN 16 THEN 'Monthly'
WHEN 32 THEN 'Monthly relative'
WHEN 64 THEN 'When SQLServer Agent starts'
END,
CASE(s.freq_subday_interval)
WHEN 0 THEN 'Once'
ELSE cast('Every '
+ right(s.freq_subday_interval,2)
+ ' '
+ CASE(s.freq_subday_type)
WHEN 1 THEN 'Once'
WHEN 4 THEN 'Minutes'
WHEN 8 THEN 'Hours'
END as char(16))
END as 'Subday Frequency',
'Next Start Date'= CONVERT(DATETIME, RTRIM(NULLIF(js.next_run_date, 0)) + ' '
+ STUFF(STUFF(REPLACE(STR(RTRIM(js.next_run_time),6,0),
' ','0'),3,0,':'),6,0,':')),
'Max Duration' = STUFF(STUFF(REPLACE(STR(maxdur.run_duration,7,0),
' ','0'),4,0,':'),7,0,':'),
'Last Run Duration' = STUFF(STUFF(REPLACE(STR(lastrun.run_duration,7,0),
' ','0'),4,0,':'),7,0,':'),
'Last Start Date' = CONVERT(DATETIME, RTRIM(lastrun.run_date) + ' '
+ STUFF(STUFF(REPLACE(STR(RTRIM(lastrun.run_time),6,0),
' ','0'),3,0,':'),6,0,':')),
'Last Run Message' = lastrun.message
FROM dbo.sysjobs j
LEFT OUTER JOIN dbo.sysjobschedules js
ON j.job_id = js.job_id
LEFT OUTER JOIN dbo.sysschedules s
ON js.schedule_id = s.schedule_id
LEFT OUTER JOIN (SELECT job_id, max(run_duration) AS run_duration
FROM dbo.sysjobhistory
GROUP BY job_id) maxdur
ON j.job_id = maxdur.job_id
-- INNER JOIN -- Swap Join Types if you don't want to include jobs that have never run
LEFT OUTER JOIN
(SELECT j1.job_id, j1.run_duration, j1.run_date, j1.run_time, j1.message
FROM dbo.sysjobhistory j1
WHERE instance_id = (SELECT MAX(instance_id)
FROM dbo.sysjobhistory j2
WHERE j2.job_id = j1.job_id)) lastrun
ON j.job_id = lastrun.job_id
ORDER BY [Job Name]

Related

how to add subjects in same days column not multiple

I have the records below. I want to show subjects when Monday in column all subjects appear on Monday with start time and end time. How do I do this?
SELECT t.teacher_name, tci.class_name, tsb.Subject_Name, tdn.DaysName,
tss.subject_start, tss.subject_end
FROM tblsubjectSchedule tss
INNER JOIN tblsubjects tsb ON tss.subject_id = tsb.Idx
INNER JOIN tblclassinfo tci ON tss.class_id = tci.Idx
INNER JOIN tbldaysnames tdn ON tss.days_id = tdn.Idx
INNER JOIN tblteacher t ON tss.techer_id = t.Idx
WHERE tss.class_id = 2 AND t.school_id = 1
Your attachment is not completely clear. Are you going to ignore teacher_name on result?
In your screenshot you haven't included 'samad teacheer' on Monday results. You want the query only for Monday date?
If you only focus on class and days and date, I got below. please refer the attachment.Let me know if it works for you and accept my answer.
SELECT t1.class_name,t1.daysname,
subject_name =REPLACE( (SELECT (subject_name+'-start:'+CONVERT(VARCHAR, subject_start, 120)+'-End:'+CONVERT(VARCHAR, subject_end, 120)) AS [data()]
FROM [practice].[dbo].[test] t2
WHERE t2.daysname = t1.daysname
ORDER BY subject_name
FOR XML PATH('')
), ' ', ';')
FROM [practice].[dbo].[test] t1
GROUP BY daysname,class_name ;
You could also add teacher name to the schedule column: see the attachment
SELECT t1.class_name,t1.daysname,
schedule =REPLACE( (SELECT (teacher_name+'-'+subject_name+'-start:'+CONVERT(VARCHAR, subject_start, 120)+'-End:'+CONVERT(VARCHAR, subject_end, 120)) AS [data()]
FROM [practice].[dbo].[test] t2
WHERE t2.daysname = t1.daysname
ORDER BY subject_name
FOR XML PATH('')
), ' ', ';')
FROM [practice].[dbo].[test] t1
GROUP BY daysname,class_name ;
Here is the query only for the 'Monday'
SELECT t1.class_name,t1.daysname,
schedule =REPLACE( (SELECT (teacher_name+'-'+subject_name+'-start:'+CONVERT(VARCHAR, subject_start, 120)+'-End:'+CONVERT(VARCHAR, subject_end, 120)) AS [data()]
FROM [practice].[dbo].[test] t2
WHERE t2.daysname = t1.daysname
ORDER BY subject_name
FOR XML PATH('')
), ' ', ';')
FROM [practice].[dbo].[test] t1 where daysname='Monday'
GROUP BY daysname,class_name ;

Getting SQL Server Activity Monitor's Output using t-SQL

How to get the SQL Server Activity Monitor's output using T-SQL???
In order to get exactly same output as Activity Monitor; I have created a following script.
If you use this script, you don't need sp_who2 or activity monitor to run.
The script that I have created will display the following things:
[Session ID]
[User Process]
[Login]
[Blocked By]
[Head Blocker]
[DatabaseName]
[Task State]
[Command]
[statement_text] --It will display the statement which is being executed presently.
[command_text] ----- It will display the Stored Procedure's Name.
[Total CPU (ms)]
'Elapsed Time (in Sec)'
[Wait Time (ms)]
[Wait Type]
[Wait Resource]
[Memory Use (KB)]
[Host Name]
[Net Address]
[Workload Group]
[Application]
My Activity Monitor's Script is as follows:
/* ACTIVITY MONITOR'S OUTPUT along with statement_text and command_text */ /* Processes */
SELECT [Session ID] = s.session_id,
[User Process] = CONVERT(CHAR(1), s.is_user_process),
[Login] = s.login_name,
[Blocked By] = ISNULL(CONVERT (varchar, w.blocking_session_id), ''),
[Head Blocker] =
CASE
-- session has an active request, is blocked, but is blocking others or session is idle but has an open tran and is blocking others
WHEN r2.session_id IS NOT NULL AND (r.blocking_session_id = 0 OR r.session_id IS NULL) THEN '1'
-- session is either not blocking someone, or is blocking someone but is blocked by another party
ELSE ''
END,
[DatabaseName] = ISNULL(db_name(r.database_id), N''),
[Task State] = ISNULL(t.task_state, N''),
[Command] = ISNULL(r.command, N''),
[statement_text] = Substring(st.TEXT, (r.statement_start_offset / 2) + 1,
( ( CASE r.statement_end_offset WHEN - 1 THEN Datalength(st.TEXT)
ELSE r.statement_end_offset
END - r.statement_start_offset ) / 2 ) + 1), ----It will display the statement which is being executed presently.
[command_text] =Coalesce(Quotename(Db_name(st.dbid)) + N'.' + Quotename(Object_schema_name(st.objectid, st.dbid)) + N'.' + Quotename(Object_name(st.objectid, st.dbid)), ''), -- It will display the Stored Procedure's Name.
[Total CPU (ms)] = r.cpu_time,
r.total_elapsed_time / (1000.0) 'Elapsed Time (in Sec)',
[Wait Time (ms)] = ISNULL(w.wait_duration_ms, 0),
[Wait Type] = ISNULL(w.wait_type, N''),
[Wait Resource] = ISNULL(w.resource_description, N''),
[Total Physical I/O (MB)] = (s.reads + s.writes) * 8 / 1024,
[Memory Use (KB)] = s.memory_usage * 8192 / 1024,
--[Open Transactions Count] = ISNULL(r.open_transaction_count,0),
--[Login Time] = s.login_time,
--[Last Request Start Time] = s.last_request_start_time,
[Host Name] = ISNULL(s.host_name, N''),
[Net Address] = ISNULL(c.client_net_address, N''),
-- [Execution Context ID] = ISNULL(t.exec_context_id, 0),
-- [Request ID] = ISNULL(r.request_id, 0),
[Workload Group] = N'',
[Application] = ISNULL(s.program_name, N'')
FROM sys.dm_exec_sessions s
LEFT OUTER JOIN sys.dm_exec_connections c ON (s.session_id = c.session_id)
LEFT OUTER JOIN sys.dm_exec_requests r ON (s.session_id = r.session_id)
LEFT OUTER JOIN sys.dm_os_tasks t ON (r.session_id = t.session_id
AND r.request_id = t.request_id)
LEFT OUTER JOIN
( -- In some cases (e.g. parallel queries, also waiting for a worker), one thread can be flagged as
-- waiting for several different threads. This will cause that thread to show up in multiple rows
-- in our grid, which we don't want. Use ROW_NUMBER to select the longest wait for each thread,
-- and use it as representative of the other wait relationships this thread is involved in.
SELECT *,
ROW_NUMBER() OVER (PARTITION BY waiting_task_address
ORDER BY wait_duration_ms DESC) AS row_num
FROM sys.dm_os_waiting_tasks ) w ON (t.session_id = w.session_id)
AND w.row_num = 1
LEFT OUTER JOIN sys.dm_exec_requests r2 ON (r.session_id = r2.blocking_session_id) OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE s.session_Id > 50 -- Ignore system spids.
ORDER BY s.session_id --,[Total CPU (ms)] desc ;
Not exactly sure what you are looking for, but this should give you something similar what you see on the activity monitor (not completely but similar).
SELECT
P.spid,
RIGHT(CONVERT(VARCHAR, DATEADD(MS, DATEDIFF(MS, P.last_batch, GETDATE()), '1900-01-01'), 121), 12) AS [BATCH_DURATION],
P.program_name,
P.hostname AS HOST_NAME,
P.loginame AS LOGIN_NAME
FROM master.dbo.sysprocesses AS P
WHERE
P.spid > 50 AND
P.status NOT IN ('background', 'sleeping') AND
P.cmd NOT IN
(
'AWAITING COMMAND',
'MIRROR HANDLER',
'LAZY WRITER',
'CHECKPOINT SLEEP',
'RA MANAGER'
)
ORDER BY 2
The reason we are looking for SPID > 50 is because processes that has ID smaller than 50 belongs to internal operations. Anything greater than 50 should be for user actions.
Also, you can see all the blockings etc. on a db, you could try something like this.
SELECT
db.name AS DB_NAME,
tl.request_session_id AS REQUESTING_SESSION,
wt.blocking_session_id AS BLOCKING_SESSION,
OBJECT_NAME(p.OBJECT_ID) AS BLOCKED_OBJECT,
tl.resource_type AS RESOURCE_TYPE,
h1.TEXT AS REQUEST_QUERY,
h2.TEXT AS BLOCKING_QUERY,
tl.request_mode
FROM sys.dm_tran_locks AS tl
INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id
INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
You can possibly combine these to get what exactly you are looking for.
Hope this helps.

Where to find date & time of currently running SQL agent job STEP?

I want to query a view or table for the currently running SQL agent job steps and when did they start.
I've tried queries below but it gives me JOB datetime rather then step datetime.
select top 100 * from msdb.dbo.sysjobsteps
select top 100 * from msdb.dbo.sysjobstepslogs
select top 100 * from msdb.dbo.sysjobhistory
exec master.dbo.xp_sqlagent_enum_jobs 1 , garbage -- gives me currently running job step
Screen Shot of desired values below from SQL Activity Monitor.
try the following
SELECT
ja.job_id as JobId,
j.name AS JobName,
ja.start_execution_date as StartDn,
ISNULL(last_executed_step_id,0)+1 AS CurrentStepId
FROM msdb.dbo.sysjobactivity ja
LEFT JOIN msdb.dbo.sysjobhistory jh ON ja.job_history_id = jh.instance_id
INNER JOIN msdb.dbo.sysjobs j ON ja.job_id = j.job_id
INNER JOIN msdb.dbo.sysjobsteps js ON ja.job_id = js.job_id AND ISNULL(ja.last_executed_step_id,0)+1 = js.step_id
INNER JOIN msdb.dbo.syssessions r ON r.session_id = ja.session_id
WHERE start_execution_date is not null
AND stop_execution_date is null;
You might check this article for further information
hope this will help you
/* Hank Freeman */
use master
go
SELECT
ja.job_id,
j.name AS job_name,
ja.start_execution_date,
--2019-06-10 18:54:31.000
getdate() as 'NOW',
'0'+Cast(Datepart(hh,(getdate() - ja.start_execution_date)) as char(2)) + ':' +
Cast(Datepart(n,(getdate() - ja.start_execution_date)) as char(2)) + ':' +
'0'+Cast(Datepart(ss,(getdate() - ja.start_execution_date)) as char(2)) as 'Duration',
Cast(DATEDIFF(n,ja.start_execution_date,getdate()) as char(5)) as 'Duration_Mins',
ISNULL(last_executed_step_id,0)+1 AS cur_exec_step_id,
Js.step_name
FROM msdb.dbo.sysjobactivity ja
LEFT JOIN msdb.dbo.sysjobhistory jh
ON ja.job_history_id = jh.instance_id
JOIN msdb.dbo.sysjobs j
ON ja.job_id = j.job_id
JOIN msdb.dbo.sysjobsteps js
ON ja.job_id = js.job_id
AND ISNULL(ja.last_executed_step_id,0)+1 = js.step_id
WHERE ja.session_id = (
SELECT TOP 1 session_id
FROM msdb.dbo.syssessions
ORDER BY session_id DESC
)
AND start_execution_date is not null
AND stop_execution_date is null
order by 2
;

Issue with Stored Procedure modify in SQL

Trying to amend a stored procedure and getting this error
Msg 156, Level 15, State 1, Procedure webopius_OrderExport, Line 14
Incorrect syntax near the keyword 'left’.
The code is
ALTER proc [dbo].[webopius_OrderExport]
AS
SET NOCOUNT ON
BEGIN
SELECT
convert(varchar, getdate(), 103) ExtractDate,
o.StoreID, o.OrderNumber OrderNumber,
o.CustomerID, o.FirstName, o.LastName, o.Email, o.AffiliateID
left(cast(o.OrderNotes as varchar(100)), 100) OrderNotes,
o.ShippingFirstName, o.ShippingLastName, o.ShippingMethod,
left(left(case o.ShippingCompany when '' then '' else o.ShippingCompany+' ' end,80)+o.ShippingAddress1, 100) ShippingAddress1,
left(o.ShippingAddress2, 100) ShippingAddress2, left(o.ShippingSuite, 30) ShippingSuite,
left(o.ShippingCity, 50) ShippingCity,
left(o.ShippingState, 50) ShippingState,
left(o.ShippingZip, 13) ShippingZip,
o.ShippingCountry ShippingCountry, o.ShippingPhone,
cast(isnull(a.ExtensionData,'') as nvarchar(200)) ShippingTitle,
o.ShippingMethodID,
convert(varchar(10), o.OrderDate, 103) as OrderDate,
left(os.OrderedProductSKU, 40) SKU,
os.Quantity,
isnull(os.OrderedProductRegularPrice, 0) OrderedProductRegularPrice,
ISNULL(os.OrderedProductPrice,0) OrderedProductPrice,
isnull(os.OrderedProductSalePrice,0) OrderedProductSalePrice ,
isnull(o.LevelHasNoTax, 0) LevelHasNoTax,
TaxRate, os.IsTaxable, OrderShippingCosts, o.OrderSubtotal SubTotal,
left(upper(o.BillingFirstName + ' ' + o.BillingLastName), 80) AS BillingName,
left(left(case o.BillingCompany when '' then '' else o.BillingCompany+' ' end,80)+o.BillingAddress1,100) BillingAddress1,
left(o.BillingAddress2, 100) BillingAddress2,
left(o.BillingSuite, 30) BillingSuite,
left(o.BillingCity, 50) BillingCity,
left(o.BillingState, 50) BillingState,
left(o.BillingZip, 8) BillingZip,
o.BillingCountry BillingCountry, o.BillingPhone,
o.CardType, o.CardName, o.CardNumber,
o.CardExpirationMonth+'/'+o.CardExpirationYear CardExpiryDate,
o.CardStartDate, o.CardIssueNumber,
o.PaymentMethod, o.LevelID, os.ProductID, os.VariantID,
c.CustomerID,
'"' + isnull(cast(c.ExtensionData as nvarchar(200)), '') + '"' ExtensionData,
m.Name Supplier, p.Name ProductName,
'"' + isnull(cast(p.ExtensionData as nvarchar(200)), '') + '"' ProdExtensionData
FROM
dbo.Orders o with (NOLOCK)
left join
orders_ShoppingCart os WITH (NOLOCK) ON os.OrderNumber = o.OrderNumber
left join
Customer c WITH (NOLOCK) on c.CustomerID = o.CustomerID
left join
Product p with (NOLOCK) on p.ProductID = os.ProductID
left join
ProductManufacturer pm with (NOLOCK) on pm.ProductID = os.ProductID
left join
Manufacturer m with (NOLOCK) on m.ManufacturerID = pm.ManufacturerID
left join
Address a with (NOLOCK) on a.AddressID = c.ShippingAddressID
WHERE
o.OrderNumber = os.OrderNumber
AND o.ShippedOn IS NULL
AND (o.TransactionState IN ('AUTHORIZED', 'CAPTURED')
OR (o.TransactionState = 'PENDING' and o.PaymentMethod='PURCHASEORDER'))
AND IsNew = 1
AND o.StoreID <> 4
ORDER BY
ordernumber
END
The column does exist in the SQL table where the left command is shown.
Any ideas where I'm going wrong?
Your code reads at about line 20
o.CustomerID, o.FirstName, o.LastName, o.Email, o.AffiliateID
left(cast(o.OrderNotes as varchar(100)),100) OrderNotes,
it should read
o.CustomerID, o.FirstName, o.LastName, o.Email, o.AffiliateID, --comma added here
left(cast(o.OrderNotes as varchar(100)),100) OrderNotes,
Easy, missing comma
You're missing a comma on the previous line, after o.AffiliateID.

How can i link a sql server job name

to the SSRS report server process that uses it? the name looks like a guid, but i need to find the reporting services reports that use it.
thanks very much
Here's a query I blogged about a while back that does the join:
;WITH cte (job_id, job_name, execution_time, execution_order)
AS
(
SELECT DISTINCT j.job_id
,j.name
,CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/')
+ SPACE(1)
+ STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':'))
,ROW_NUMBER() OVER (PARTITION BY j.job_id ORDER BY CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/')
+ SPACE(1)
+ STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':')) DESC)
FROM msdb.dbo.sysjobs j
INNER JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
LEFT OUTER JOIN msdb.dbo.sysjobhistory jh ON j.job_id = jh.job_id
WHERE c.name ='Report Server'
)
SELECT
x.job_name
,c.name
,x.execution_time
,c.path
,su.description
,CONVERT(varchar(max), su.ExtensionSettings) as ExtensionSettings
,'EXEC msdb..sp_start_job ''' + x.job_name + '''' as SQLStatement
FROM cte x
INNER JOIN dbo.Schedule sc ON x.job_name = CONVERT(varchar(100), sc.ScheduleID)
INNER JOIN dbo.ReportSchedule rs ON sc.ScheduleID = rs.ScheduleID
INNER JOIN dbo.Subscriptions su ON rs.SubscriptionID = su.SubscriptionID
INNER JOIN dbo.Catalog c ON su.Report_OID = c.ItemID
WHERE execution_order = 1
ORDER BY 3, 2
There doesn't appear to be a straightforward method to find this out.
The following query lists the subscription IDs and the reports to which they link
select s.SubscriptionID, c.Path
from ReportServer.dbo.Subscriptions as s
JOIN ReportServer.dbo.Catalog as c
on ItemID = Report_OID
The subscription ID is then referenced inside the job step, in the following format.
exec ReportServer.dbo.AddEvent #EventType='TimedSubscription', #EventData='~subscriptionID~'
It should be possible to write a query to join it all together, but I don't have time right now. I will try and update the question later.

Resources