分组和PIVOT在同一个T-SQL中

时间:2014-11-10 12:38:24

标签: tsql

我尝试将每个工作和每周的工作历史记录分组,并获得工作的最大,平均和最小持续时间,以及该工作周内发生了多少次失败,成功,重试和取消把所有东西都放到一个html表中并邮寄它。

但问题是我不知道PIVOT如何获得每周每个工作的每个状态的总和。 我需要做些什么呢?

DECLARE @body NVARCHAR(MAX)
DECLARE @subjectstring NVARCHAR(256)

SET     @body =  N'<H4>SQL Job history on ' + @@servername + '</H4>' +
    + N'<table border="1">'
    + N'<tr><th>week</th><th>name</th><th>max</th><th>avg</th><th>min</th><th>Failed</th><th>Succeeded</th><th>Retry</th><th>Canceled</th></tr>'
    + CAST((
SELECT  [master].[dbo].[cfn_F_ISO_WEEK_OF_YEAR](CONVERT(varchar(10), convert(datetime, CAST([run_date] AS NVARCHAR(8)), 112), 23)) AS [td]
        ,j.name AS td
               ,MAX(h.run_duration) AS [td]
               ,AVG(h.run_duration) AS [td]
               ,MIN(h.run_duration) AS [td]
               ,[0] AS [td]
               ,[1] AS [td]
               ,[2] AS [td]
               ,[3] AS [td]
FROM   (msdb.dbo.sysjobs j 
       INNER JOIN msdb.dbo.sysjobhistory h 
               ON h.job_id = j.job_id)
    PIVOT(SUM(h.run_status) FOR [MYGROUPBY] IN ([0], [1], [2],[3]))
WHERE j.name IN ( 'IndexOptimize - ALL_DATABASES', 'BizTalkProdIndexMaintenance.Subplan_1', 'Backup BizTalk Server (BizTalkMgmtDb)', 'SSIS Server Maintenance Job')  AND 
    step_id = 0 
    AND [master].[dbo].[cfn_F_ISO_WEEK_OF_YEAR](CONVERT(varchar(10), convert(datetime, CAST([run_date] AS NVARCHAR(8)), 112), 23)) > [master].[dbo].[cfn_F_ISO_WEEK_OF_YEAR](GETDATE())-2
    GROUP BY 
        [master].[dbo].[cfn_F_ISO_WEEK_OF_YEAR](CONVERT(varchar(10), convert(datetime, CAST([run_date] AS NVARCHAR(8)), 112), 23))
        ,j.name 
ORDER  BY [master].[dbo].[cfn_F_ISO_WEEK_OF_YEAR](CONVERT(varchar(10), convert(datetime, CAST([run_date] AS NVARCHAR(8)), 112), 23)) ASC
        FOR XML RAW('tr'), ELEMENTS
    ) AS NVARCHAR(MAX))
    + N'</table>'          


SET @subjectstring = 'x - Job history ' + CAST(@@servername as nvarchar(64))

EXEC msdb.dbo.sp_send_dbmail @recipients='mymail', @subject = @subjectstring, @body = @body, @body_format = 'HTML', @profile_name = 'mail.customer.se'
GO

我想要一个像这样的结果

name, week, maxduration, avgduration, minduration, 0, 1, 2, 3
--------------------------------------
job1, 46, 70, 56, 45, 7, 1, 0, 1

1 个答案:

答案 0 :(得分:0)

花了一段时间,但我找到了解决问题的方法:

DECLARE @body NVARCHAR(MAX)
DECLARE @subjectstring NVARCHAR(256)

IF OBJECT_ID('tempdb..#MyResultTable', 'U') IS NOT NULL 
    DROP TABLE #MyResultTable

; 
WITH mytable 
     AS (SELECT [master].[dbo].[Cfn_f_iso_week_of_year]( 
                           msdb.dbo.Agent_datetime(h.run_date, h.run_time)) AS 
                [Week] 
                , 
                msdb.dbo.Agent_datetime(h.run_date, h.run_time) 
                AS RunTime, 
                j.NAME, 
                master.dbo.cfn_agent_time(h.run_duration) as run_duration, 
                h.run_status, 
                h.instance_id 
         FROM   msdb.dbo.sysjobs j 
                INNER JOIN msdb.dbo.sysjobhistory h 
                        ON h.job_id = j.job_id 
         WHERE  h.step_id = 0 
         ), 
     resulttable 
     AS (SELECT pt.[week], 
                pt.[name], 
                pt.run_duration, 
                [0] AS Failed, 
                [1] AS Succeeded, 
                [2] AS Retry, 
                [3] AS Canceled 
         FROM   mytable 
                PIVOT(Count(mytable.instance_id) 
                     FOR mytable.run_status IN ([0], 
                                                [1], 
                                                [2], 
                                                [3])) AS pt) 
SELECT RT.[week], 
       RT.[name], 
       Sum(RT.failed)         AS Failed, 
       Sum(RT.succeeded)      AS Succeeded, 
       Sum(RT.retry)          AS Retry, 
       Sum(RT.canceled)       AS Canceled, 
       MAX(RT.[run_duration]) AS [Max], 
       AVG(RT.[run_duration]) AS [Avg], 
       MIN(RT.[run_duration]) AS [Min] 
       INTO #MyResultTable
FROM   resulttable AS RT 
WHERE RT.[Week] > [master].[dbo].[Cfn_f_iso_week_of_year](GETDATE())-2
GROUP  BY RT.[week], 
          RT.[name] 
ORDER  BY [week]



SET     @body =  N'<H4>SQL Job history on ' + @@servername + ' - Version 2</H4>' +
    + N'<table border="1">'
    + N'<tr><th>week</th><th>name</th><th>Failed</th><th>Succeeded</th><th>Retry</th><th>Canceled</th><th>Max</th><th>Avg</th><th>Min</th></tr>'
    + CAST((
    SELECT 
         t.Week AS [td]
         ,t.name AS [td]
         ,t.Failed AS [td]
         ,t.Succeeded AS [td]
         ,t.Retry AS [td]
         ,t.Canceled AS [td]
         ,REPLACE(CAST(t.Max AS DECIMAL)/86400, '.', ',') AS [td]
         ,REPLACE(CAST(t.Avg AS DECIMAL)/86400, '.', ',') AS [td]
         ,REPLACE(CAST(t.Min AS DECIMAL)/86400, '.', ',') AS [td]
    FROM #MyResultTable t
    ORDER BY t.[week]
        FOR XML RAW('tr'), ELEMENTS
    ) AS NVARCHAR(MAX))
    + N'</table>'          

IF OBJECT_ID('tempdb..#MyResultTable', 'U') IS NOT NULL 
    DROP TABLE #MyResultTable


SET @subjectstring = 'CustomerName - Job history ' + CAST(@@servername as nvarchar(64))

EXEC msdb.dbo.sp_send_dbmail @recipients='email1@customer.com;email2@customer.com', @subject = @subjectstring, @body = @body, @body_format = 'HTML', @profile_name = 'mail.customer.se'
GO