SQL Server-每天汇总每个用户的错误数

时间:2018-10-26 19:22:00

标签: sql sql-server ssms

我维护的应用程序将用户错误存储在SQL Server表中。发生错误时,它会记下导致该错误的人员的用户名,时间,错误消息以及其他一些内部管理工作。

我正在尝试建立一个报告,在该报告中我们可以看到过去一年中每天的“前3个”错误-每天错误最多的三个用户,每天错误最常见的三种类型等等

我的目标是这样的:

DATE       USER1    ERR_COUNT1    USER2    ERR_COUNT2    USER3    ERR_COUNT3
1/1/18     BOB      70            BILL     50            JOE      30
1/2/18     JILL     55            JOY      30            BOB      20
... 

我已经设置了一个粗糙的循环来从我们的错误日志中提取此数据,但是当我运行它时,出现错误There is already an object named '#TempErrorLog'in the database。下面的循环代码:

DECLARE @StartDate AS DATE,
        @EndDate AS DATE

SET @StartDate = '2018.1.1'

WHILE @StartDate <= CONVERT(DATE, GETDATE())
    BEGIN
        SET @EndDate = DATEADD(DAY, 1,  @StartDate) 

        SELECT @StartDate AS date_err,
               ( u.name_frst+' '+u.name_lst ) AS user_err,
               COUNT(e.id_err) AS count_err
        INTO dbo.#TempErrLog
        FROM err_log AS e
             LEFT JOIN users AS u ON e.id_user = u.id_user
        WHERE e.dttm_err >= @StartDate AND
              e.dttm_err < @EndDate AND
              e.id_user <> 'system'
        GROUP BY ( u.name_frst+' '+u.name_lst )
        ORDER BY count_err DESC;

        SET @StartDate = DATEADD(DAY, 1,  @StartDate)

            CONTINUE
    END

SELECT * FROM #TempErrLog

我的猜测是,每次循环迭代时,它都试图创建一个新的临时表。我在这里应该使用更好的方法吗?

1 个答案:

答案 0 :(得分:1)

您可以使用条件聚合和row_number()来调整它。对于您问题中的结果:

with ue as (
      select e.*, (u.name_frst + ' ' + u.name_lst ) as user_name,
             cast(e.dttm_err as date) as err_date
      from err_log e join
           users u
           on e.id_user = u.id_user
     )
select u.err_date,
       max(case when u.seqnum = 1 then u.user_name end) as user_1,
       max(case when u.seqnum = 1 then u.cnt end) as cnt_1,
       max(case when u.seqnum = 2 then u.user_name end) as user_2,
       max(case when u.seqnum = 2 then u.cnt end) as cnt_2,
       max(case when u.seqnum = 3 then u.user_name end) as user_3,
       max(case when u.seqnum = 3 then u.cnt end) as cnt_3
from (select err_date, user_name, count(*) as cnt,
             row_number() over (partition by err_date order by count(*) desc) as seqnum
      from ul
      group by err_date, user_name
     ) u 
group by u.err_date