我们运营的网站不允许共享登录详细信息,但从未构建系统来阻止这些用户。现在,管理层想要一份正在分享的人的报告。我很确定我们可以通过分析统计数据库找到它们。
我检测共享登录的想法是在每个月末查询统计信息表(MSSQL 2008)并生成一个嫌疑人列表。为了捕获它们,我需要一个显示“切换”会话/ ipaddress的查询。
例如,允许以下内容:
DateTime, UserId, SessionId, IpAddress
12Feb13 16:30, 10, ABC, x.x.x.x
12Feb13 16:32, 10, ABC, x.x.x.x
12Feb13 16:34, 10, DEF, y.y.y.y
12Feb13 16:36, 10, DEF, y.y.y.y
以下是不允许:
DateTime, UserId, SessionId, IpAddress
12Feb13 16:30, 10, ABC, x.x.x.x
12Feb13 16:32, 10, DEF, y.y.y.y
12Feb13 16:34, 10, ABC, x.x.x.x
12Feb13 16:36, 10, DEF, y.y.y.y
问题是如何在查询成千上万的条目时有效地做到这一点?
答案 0 :(得分:2)
注意:我删除了之前的CTE答案,因为我能使其工作的唯一方法是使用SQL 2008上没有的LAG
。 ,我想出了一些运行得更快的东西。
以下将数据拆分为两个CTE,第一个返回用户发生sessionID的时间范围,第二个是ip地址的范围。如果会话在ip地址范围内开始,但在该范围之外结束,则会话必须是不同IP地址的一部分。同样,如果会话在ip之前启动,但在ip内完成,那么它也很糟糕。
此解决方案假定sessionID只能在每个用户使用一次 - 一旦他们的会话结束ip,id号就不能在以后使用。
SELECT s.UserId, s.SessionId, s.IpAddress, i.IpAddress, s.MinDate [sMin], s.MaxDate [sMax],
i.MinDate [iMin], i.MaxDate [iMax]
FROM (
SELECT UserID, SessionID, IPAddress, MIN(DT) MinDate, MAX(DT) MaxDate
FROM #USERLOG
GROUP BY UserID, SessionID, IPAddress
) AS s
INNER JOIN (
SELECT UserID, IPAddress, MIN(DT) MinDate, MAX(DT) MaxDate
FROM #USERLOG ipLog
GROUP BY UserID, IPAddress
) AS i ON
s.UserID = i.UserID
AND s.IpAddress != i.IpAddress
AND (
(s.MinDate < i.MaxDate AND s.MaxDate > i.MaxDate) OR
(s.MinDate < i.MinDate AND s.MaxDate > i.MinDate))
为了获得最佳效果,您需要UserID, Session, IPAddress
和UserID, SessionID
的索引。