我目前有一个表,可以在用户登录和注销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
发生的最新computer
和location
来实现,但运行速度非常慢,因为我们获得了数千条日志周。我想知道是否有更有效的查询,我没想出来。
我正在运行MSSQL
答案 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