select
j.name as 'JobName',
run_date,
run_time,
msdb.dbo.agent_datetime(run_date, run_time) as 'RunDateTime',
h.run_duration,
((run_duration/10000*3600 + (run_duration/100)%100*60 + run_duration%100 + 31 ) / 60)
as 'RunDurationMinutes'
From msdb.dbo.sysjobs j
INNER JOIN msdb.dbo.sysjobhistory h
ON j.job_id = h.job_id
where j.enabled = 1
AND
((run_duration/10000*3600 + (run_duration/100)%100*60 + run_duration%100 + 31 ) / 60) > 1
The above SQL query will fetch list of a all jobs that takes more then a minute.
But it give a huge list, i dont want that all.
I just want last 2 run of every jobs.
I tried using top 2 and order by desc but it does not list all the jobs in the list.
I just want last 2 run of every job.
Any suggestions.?
Look at ROW_NUMER() ranging function:
select * from (
select
j.name as 'JobName',
run_date,
run_time,
msdb.dbo.agent_datetime(run_date, run_time) as 'RunDateTime',
h.run_duration,
((run_duration/10000*3600 + (run_duration/100)%100*60 + run_duration%100 + 31 ) / 60)
as 'RunDurationMinutes',
ROW_NUMBER() OVER(PARTITION BY j.name ORDER BY msdb.dbo.agent_datetime(run_date, run_time) DESC) NROW
From msdb.dbo.sysjobs j
INNER JOIN msdb.dbo.sysjobhistory h
ON j.job_id = h.job_id
where j.enabled = 1
AND
((run_duration/10000*3600 + (run_duration/100)%100*60 + run_duration%100 + 31 ) / 60) > 1
) t where nrow < 3
To make things clear I have done:
Add new column to your query:
ROW_NUMBER() OVER(PARTITION BY j.name ORDER BY msdb.dbo.agent_datetime(run_date, run_time) DESC) NROW
This column group by all the records by j.name field and number each group by 'RunDateTime' field.
Now we need to get all the records where NROW == 1 or NROW == 2. I have created subquery (not sure it is a best solution) and and WHERE condition
select * from ( ... ) t where nrow < 3
Try this
SELECT
r.session_id, r.start_time,
TotalElapsedTime_ms = r.total_elapsed_time
, r.[status]
, r.command
, DatabaseName = DB_Name(r.database_id)
, r.wait_type
, r.last_wait_type
, r.wait_resource
, r.cpu_time
, r.reads
, r.writes
, r.logical_reads
, t.[text] AS [executing batch]
, SUBSTRING(
t.[text], r.statement_start_offset / 2,
( CASE WHEN r.statement_end_offset = -1 THEN DATALENGTH (t.[text])
ELSE r.statement_end_offset
END - r.statement_start_offset ) / 2
) AS [executing statement]
, p.query_plan
FROM
sys.dm_exec_requests r
CROSS APPLY
sys.dm_exec_sql_text(r.sql_handle) AS t
CROSS APPLY
sys.dm_exec_query_plan(r.plan_handle) AS p
ORDER BY
r.total_elapsed_time DESC;
Related
Below is my query but when I include my CapturedDateTime and IsOutOfSpec columns then it returns multiple rows but I only want one record to be returned that displays the averages of the last 10 records. So it must return the average PartWeight, average SprueWeight and average Bom Weight for a specified stock code.
--Last 10 Average Report
SELECT Top 10 c.StockCode,i.LongDesc,
AVG(c.PartWeightGram) AS 'Part Weight Average',
AVG(c.SprueWeightGram) AS 'Sprue Weight Average' ,
AVG(c.TolerancePercentage) AS 'Tolerance Average' ,
AVG(c.BomWeightKG * 1000) AS 'Bom Weight Average' ,
AVG(c.PartWeightGram + (c.SprueWeightGram / 2)) - (c.BomWeightKG) AS 'Variance To Syspro Average',
AVG((((((c.PartWeightGram + c.SprueWeightGram / 2))) - (c.BomWeightKG * 1000)) / (c.BomWeightKG * 1000)) * 100) AS 'VarianceToSysproPct'
FROM tblComponentWeightCheck c
LEFT JOIN [Mercury].[EncoreCompanyA].dbo.InvMaster i ON c.StockCode = i.StockCode
WHERE c.StockCode='000-256966-020' And Deleted = 'False'
GROUP BY c.StockCode,i.LongDesc,c.BomWeightKG
ORDER BY c.StockCode DESC
This is my Table:
SELECT [ComponentWeightCheckID]
,[EmpID]
,[StockCode]
,[Process]
,[PartWeightGram]
,[SprueWeightGram]
,[BomWeightKG]
,[TolerancePercentage]
,[AssetID]
,[CapturedDateTime]
,[Hostname]
,[Username]
,[IsOutOfSpec]
,[Tool]
,[Deleted]
FROM [dbo].[tblComponentWeightCheck]
Sample Data:
SELECT Top 10 c.StockCode,i.LongDesc AS 'Description',
(SELECT TOP 10 AVG(PartWeightGram) FROM tblComponentWeightCheck c WHERE c.StockCode = '000-256966-020' GROUP BY c.StockCode ) AS 'Part Weight Average',
(SELECT TOP 10 AVG([SprueWeightGram]) FROM tblComponentWeightCheck c WHERE c.StockCode = '000-256966-020' GROUP BY c.StockCode ) AS 'Sprue Weight Average',
(SELECT TOP 10 AVG(c.TolerancePercentage) FROM tblComponentWeightCheck c WHERE c.StockCode = '000-256966-020' GROUP BY c.StockCode ) AS 'Tolerance Average',
(SELECT TOP 10 AVG([BomWeightKG]) FROM tblComponentWeightCheck c WHERE c.StockCode = '000-256966-020' GROUP BY c.StockCode ) AS 'Bom Weight Average',
(SELECT TOP 10 AVG((c.PartWeightGram + (c.SprueWeightGram / 2)) - (c.BomWeightKG * 1000)) FROM tblComponentWeightCheck c WHERE c.StockCode = '000-256966-020' GROUP BY c.StockCode ) AS 'Variance To Syspro Average',
(SELECT TOP 10 AVG((((((c.PartWeightGram + c.SprueWeightGram / 2))) - (c.BomWeightKG * 1000)) / (c.BomWeightKG * 1000)) * 100) FROM tblComponentWeightCheck c WHERE c.StockCode = '000-256966-020' GROUP BY c.StockCode ) AS 'Variance To Syspro & Average'
FROM tblComponentWeightCheck c
LEFT JOIN [Mercury].[EncoreCompanyA].dbo.InvMaster i ON c.StockCode = i.StockCode
WHERE c.StockCode = '000-256966-020'
AND CONVERT(Date, c.CapturedDateTime) Between '2021-04-01' AND '2021-05-24'
GROUP BY c.StockCode, i.LongDesc
This image shows the result of the above query.It only returns 1 row which it should but it is missing my CapturedDateTime AND IsOutOfSpec columns, as soon as i include those then it returns multiple records which i don't want
Presumably, the LEFT JOIN is not needed -- it would seem odd to have stock codes that are not in the inventory master.
You can do this pretty easily using APPLY:
SELECT Top 10 i.StockCode, i.LongDesc,
AVG(c.PartWeightGram) AS Part_Weight_Average,
AVG(c.SprueWeightGram) AS Sprue_Weight_Average,
AVG(c.TolerancePercentage) AS Tolerance_Average,
AVG(c.BomWeightKG * 1000) AS Bom_Weight_Average,
AVG(c.PartWeightGram + (c.SprueWeightGram / 2)) - (c.BomWeightKG) AS Variance_To_Syspro_Average,
AVG((((((c.PartWeightGram + c.SprueWeightGram / 2))) - (c.BomWeightKG * 1000)) / (c.BomWeightKG * 1000)) * 100) AS VarianceToSysproPct
FROM [Mercury].[EncoreCompanyA].dbo.InvMaster i CROSS APPLY
(SELECT TOP (10) c.*
FROM tblComponentWeightCheck c
WHERE c.StockCode = i.StockCode
ORDER BY c.CapturedDateTime DESC
) c
WHERE i.StockCode = '000-256966-020' AND Deleted = 'False'
GROUP BY i.StockCode, i.LongDesc, c.BomWeightKG
ORDER BY i.StockCode DESC;
For performance, I recommend indexes on tblComponentWeightCheck(StockCode, CapturedDateTime DESC) and InvMaster(StockCode).
Judging by your query, you should use a window function and a subquery instead of top 10. Following an example. However, you will have to provide the sorting criteria for the ROW_NUMBER() in order to define your "TOP 10"...
--Last 10 Average Report
SELECT c.StockCode,c.LongDesc,
AVG(c.PartWeightGram) AS 'Part Weight Average',
AVG(c.SprueWeightGram) AS 'Sprue Weight Average' ,
AVG(c.TolerancePercentage) AS 'Tolerance Average' ,
AVG(c.BomWeightKG * 1000) AS 'Bom Weight Average' ,
AVG(c.PartWeightGram + (c.SprueWeightGram / 2)) - (c.BomWeightKG) AS 'Variance To Syspro Average',
AVG((((((c.PartWeightGram + c.SprueWeightGram / 2))) - (c.BomWeightKG * 1000)) / (c.BomWeightKG * 1000)) * 100) AS 'VarianceToSysproPct'
FROM (
SELECT c.StockCode
,i.LongDesc
,c.PartWeightGram
,c.SprueWeightGram
,c.TolerancePercentage
,c.BomWeightKG
,c.PartWeightGram
,c.PartWeightGram
,ROW_NUMBER() OVER (PARTITION BY c.StockCode ORDER BY ...) AS rn
FROM tblComponentWeightCheck c
LEFT JOIN [Mercury].[EncoreCompanyA].dbo.InvMaster i ON c.StockCode = i.StockCode
WHERE Deleted = 'False'
) c
WHERE c.StockCode='000-256966-020'
AND rn <= 10
GROUP BY c.StockCode,c.LongDesc,c.BomWeightKG
ORDER BY c.StockCode DESC
How can I find median in sql. I am trying
select
date,
sum(amount),
median(amount),
count(user)
from table
group by 1
It shows an error that
function median(double precision) does not exist
Try if this standard sql works.
select
t.[date]
,sum(amount) ttl_amount
,(select sum(s.amount) / (select ((count(*) + 1) % 2) + 1 from #table s where s.[date] = t.[date])
from (select s.amount
from #table s
where t.date = s.date
order by s.amount asc
offset (select ((count(*) - (count(*) + 1) % 2) / 2) from #table s where s.[date] = t.[date]) rows fetch next
(select ((count(*) + 1) % 2) + 1 from #table s where s.[date] = t.[date]) rows only ) s ) median
,count(distinct [user]) dst_user
from #table t
group by [date]
Anyone know how I can change the Total Median near bottom to show an average of the median instead? For some reason, the Total Median is always 100. Not sure what I should do.
Thanks in advance for any ideas! Current results also below.
WITH CTE AS (
SELECT DISTINCT c.CaseID AS CaseID,
DATEDIFF(d, c.CaseAddDt, coip.DispoDt) AS DaysApart
, DATEPART(month,c.CaseAddDt) AS [Month]
, DATEPART(year,c.CaseAddDt) AS [Year]
, CAST(DATEPART(year,c.CaseAddDt) AS varchar) + '|' + CASE WHEN DATEPART(month,c.CaseAddDt) IN (10,11,12) THEN CAST(DATEPART(month,c.CaseAddDt) AS varchar) ELSE '0' + CAST(DATEPART(month,c.CaseAddDt) AS varchar) END AS Srt
FROM jw50_Case c
JOIN jw50_CaseInvPers def ON def.CaseID = c.CaseID
AND def.InvolveTypeMasterCode = 1
JOIN
jw50_CountInvPers coip ON coip.CaseID = c.CaseID
AND coip.CaseInvPersID = def.CaseInvPersID
AND coip.DispoCode IN ('CODE','CODE')
AND coip.CountNum > 0
OUTER APPLY (
SELECT TOP 1 caz.CaseAgencyID
FROM jw50_CaseAgency caz
WHERE caz.CaseID = c.CaseID
AND caz.AgencyCode = 'ABC'
AND caz.NumberTypeCode IN ('i#','in#')) caz
WHERE
EXISTS (SELECT 1 FROM jw50_CaseAttributes ca WHERE ca.CaseID = c.CaseID AND ca.CaseAttributeCode = 'oa7')
AND caz.CaseAgencyID IS NOT NULL
AND c.CaseStatusCode <> 'AAA'
AND c.CaseAddDt BETWEEN '01/01/2017' AND '08/01/2017'
AND c.CaseAddDt <= coip.DispoDt)
SELECT a.CaseID,
a.Month
, a.Year
, a.DaysApart
, a.Srt
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a.DaysApart) OVER (PARTITION BY a.Month, a.Year) AS MonMedian
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a.DaysApart) OVER (PARTITION BY 1) AS TotalMedian
FROM CTE a
Results:
SELECT jobs.Job_ID AS JobID ,
jobs.NAME AS JobName ,
act.start_execution_date AS StartExecutionDate ,
AVG(FLOOR(run_duration / 100)) AS AvgDurationMin ,
CASE
--If job average less than 5 minutes then limit is avg+10 minutes
WHEN AVG(FLOOR(run_duration / 100)) <= 5
THEN ( AVG(FLOOR(run_duration / 100)) ) + 2
--If job average greater than 5 minutes then limit is avg*limit percentage
ELSE ( AVG(FLOOR(run_duration / 100))
)
END AS DurationLimit ,
DATEDIFF(MI, act.start_execution_date, GETDATE()) AS [CurrentDuration]
FROM #currently_running_jobs crj
INNER JOIN msdb..sysjobs AS jobs ON crj.job_id = jobs.job_id
INNER JOIN msdb..sysjobactivity AS act ON act.job_id = crj.job_id
AND act.stop_execution_date IS NULL
AND act.start_execution_date IS NOT NULL
INNER JOIN msdb..sysjobhistory AS hist ON hist.job_id = crj.job_id
AND hist.step_id = 0
WHERE crj.job_state = 1 --and jobs.NAME = 'long_running_testing'
GROUP BY jobs.job_ID ,
jobs.NAME ,
act.start_execution_date ,
DATEDIFF(MI, act.start_execution_date, GETDATE())
HAVING CASE WHEN AVG(FLOOR(run_duration / 100)) <= 5
THEN (AVG(FLOOR(run_duration / 100))) + 2
--THEN ( AVG(FLOOR(run_duration / 100)) ) + 1
ELSE ( AVG(FLOOR(run_duration / 100))
)
END < DATEDIFF(MI, act.start_execution_date, GETDATE())
Can someone please help me to extract the average run_duration of recent three entries of job's partitioned by job_name?
Please find the below script which I used to extract information
of recent three run_duration partitioned by job_name, but it
calculates the average of all run_duration .
Here I need only the recent three run_duration average count.
SELECT top 1 with ties jobs.Job_ID AS JobID , AVG(FLOOR(run_duration/100%100 )),
jobs.NAME AS JobName ,
act.start_execution_date AS StartExecutionDate
from msdb..sysjobs AS jobs
inner join msdb..sysjobactivity AS act ON act.job_id = jobs.job_id
INNER JOIN msdb..sysjobhistory AS hist ON hist.job_id = jobs.job_id AND hist.step_id = 0
GROUP BY jobs.job_ID ,
jobs.NAME
, act.start_execution_date ,hist.run_duration,
DATEDIFF(MI, act.start_execution_date, GETDATE())
order by case when row_number() over (partition by jobs.NAME order by hist.run_duration desc) <= 3 then 0 else 1 end;
Perhaps a CTE would simplify it.
with SeqByJob_cte as ( SELECT jobs.NAME AS JobName
,hist.run_duration
,row_number() over(partition by jobs.NAME order by act.start_execution_date desc) as seq
from msdb..sysjobs AS jobs
inner join msdb..sysjobactivity AS act ON act.job_id = jobs.job_id
INNER JOIN msdb..sysjobhistory AS hist ON hist.job_id = jobs.job_id AND hist.step_id = 0)
select avg(run_duration) as AvgOf3MostRecentRuns
,CASE
--If job average less than 5 minutes then limit is avg+10 minutes
WHEN AVG(FLOOR(run_duration / 100)) <= 5
THEN ( AVG(FLOOR(run_duration / 100)) ) + 2
--If job average greater than 5 minutes then limit is avg*limit percentage
ELSE ( AVG(FLOOR(run_duration / 100))
)
END AS DurationLimit
,JobName
from SeqByJob_cte
where seq <= 3
group by JobName
I need help with a query that check the MSDB-database for SQL Server Agent Job results. My query is as follows:
SELECT CONVERT(VARCHAR(30), Serverproperty('ServerName')),
a.run_status,
b.run_requested_date,
c.name,
CASE c.enabled
WHEN 1 THEN 'Enabled'
ELSE 'Disabled'
END,
CONVERT(VARCHAR(10), CONVERT(DATETIME, Rtrim(19000101))+(a.run_duration *
9 +
a.run_duration % 10000 * 6 + a.run_duration % 100 * 10) / 216e4, 108),
b.next_scheduled_run_date
FROM (msdb.dbo.sysjobhistory a
LEFT JOIN msdb.dbo.sysjobactivity b
ON b.job_history_id = a.instance_id)
JOIN msdb.dbo.sysjobs c
ON b.job_id = c.job_id
ORDER BY c.name
So far so good, but running it returns several results for the same jobs depending on how many times they have ran up until the query. This is no good. I want only one result per job, and only the latest.
If I add the the string:
WHERE b.session_id=(SELECT MAX(session_id) from msdb.dbo.sysjobactivity)
It works better, but then it only lists the latest jobs depending on the session_id parameter. This will exclude jobs that haven't run for a while and is not good either.
Can someone help me with this?
I have tried with DISTINCT and/or GROUP BY but can't get it to work.
with cte
AS (SELECT
Convert(varchar(30), SERVERPROPERTY('ServerName')) AS ServerName,
a.run_status,
b.run_requested_date,
c.name,
CASE c.enabled
WHEN 1 THEN 'Enabled'
Else 'Disabled'
END
AS Enabled,
CONVERT(VARCHAR(10), CONVERT(DATETIME, RTRIM(19000101))+(a.run_duration
* 9 +
a.run_duration % 10000 * 6 + a.run_duration % 100 * 10) / 216e4, 108)
AS run_duration,
b.next_scheduled_run_date,
ROW_NUMBER() over (partition by b.job_id ORDER BY b.run_requested_date
DESC) AS RN
FROM (msdb.dbo.sysjobhistory a
LEFT JOIN msdb.dbo.sysjobactivity b
ON b.job_history_id = a.instance_id)
join msdb.dbo.sysjobs c
on b.job_id = c.job_id)
SELECT *
FROM cte
WHERE RN = 1
ORDER BY name