循环日志记录的最有效方法

时间:2014-08-18 15:19:00

标签: sql sql-server

我目前有一个表,可以在用户登录和注销PC时记录。表的设计如下:

LogTable:

[event_time]|[userID]|[CompName]|[event_type]|[Location]

登录计算机的人的一个例子是:

2014-08-18 10:11:17.000 | smith217 | library2123 | 1 | 13

大部分表格都是自我解释的。事件类型是用户是登录还是注销。 a' 1'将登录,并且' 0'会退出。

我正在寻找循环浏览这些记录的最有效方法,并找出特定位置可用的计算机。

我目前正在使用这个:

SELECT CompName, 
       event_type 
FROM   LogTable o
WHERE  Location = 13 
       AND EXISTS (SELECT * 
                   FROM   LogTable i 
                   GROUP  BY CompName 
                   HAVING Max(i.[event_time]) = o.[event_time] 
                          AND i.CompName = o.CompName) 
ORDER  BY CompName 

这可以通过在event_time获取每个CompName发生的最新computerlocation来实现,但运行速度非常慢,因为我们获得了数千条日志周。我想知道是否有更有效的查询,我没想出来。

我正在运行MSSQL

2 个答案:

答案 0 :(得分:2)

好的,假设每个PC名称至少在日志中一次。

LogCTE中,我按row_number()按降序添加compname/Location,因此'1'始终是最后一个事件...所以如果你选择所有的1只是你的最后一个事件是它,一个输入/输出。

如果您发现这表现不佳,那么我会查看执行计划,看看是否有任何索引可能需要帮助提高性能。

例如:

/* create a table to test with*/
declare @log table (event_time datetime, userid varchar(15), compname varchar(15), eventtype int, location int)
/* add some fake data to test with */
insert into @log
select '2014-08-18 10:11:17.000','smith217','library2123',1,13 union
select '2014-08-18 10:12:17.000','smith217','library2123',0,13 union
select '2014-08-18 10:13:17.000','jones217','library2123',1,13 union
select '2014-08-18 10:14:17.000','smith217','library2124',1,13 union
select '2014-08-18 10:15:17.000','hemmingway217','library2125',1,13 union
select '2014-08-18 10:16:17.000','hemmingway217','library2125',0,13

/* CTE = computed table expression */
/* CTE's must be used immediately following creation, and are only good for ONE query */
;with LogCTE AS
(
    /* cte content, is * from @log our test table */
    /* adding a row_number(), in this case partitioned by compname/location in descending order */
    select *,
           ROW_NUMBER() OVER(PARTITION BY COMPNAME, LOCATION ORDER BY EVENT_TIME DESC) AS LastEvent
    from @log
)

/* cte looks like this if you did select * from logcte */
/*
event_time              userid          compname    eventtype   location    LastEvent
2014-08-18 10:13:17.000 jones217        library2123 1           13          1
2014-08-18 10:12:17.000 smith217        library2123 0           13          2
2014-08-18 10:11:17.000 smith217        library2123 1           13          3
2014-08-18 10:14:17.000 smith217        library2124 1           13          1
2014-08-18 10:16:17.000 hemmingway217   library2125 0           13          1
2014-08-18 10:15:17.000 hemmingway217   library2125 1           13          2
*/

/* we only want the last action per PC, so select lastevent=1 and add your other conditions */
select compname, eventtype
from LogCTE
where LastEvent=1
and location=13

答案 1 :(得分:0)

@JiggsJedi ..感谢您生成数据。

@EdwardG ..如果您已经有一个标识列并已建立索引,您可以尝试下面的示例,它根据Location和CompName获取最后一个条目。如果您有大量记录,则排序会给您带来性能影响。

    declare @log table (id int identity(1,1), event_time datetime, userid varchar(15), compname varchar(15), eventtype int, location int)

insert into @log
select '2014-08-18 10:11:17.000','smith217','library2123',1,13 union
select '2014-08-18 10:12:17.000','smith217','library2123',0,13 union
select '2014-08-18 10:13:17.000','jones217','library2123',1,13 union
select '2014-08-18 10:14:17.000','smith217','library2124',1,13 union
select '2014-08-18 10:15:17.000','hemmingway217','library2125',1,13 union
select '2014-08-18 10:16:17.000','hemmingway217','library2125',0,13



select compinfo.*
from @log compinfo
inner join
(
    select max(id) as id, Location, CompName
    from @log
    where Location = 13
    group by location, compname
) lastinfo
on compinfo.id = lastinfo.id