我维护的应用程序将用户错误存储在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
我的猜测是,每次循环迭代时,它都试图创建一个新的临时表。我在这里应该使用更好的方法吗?
答案 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