1

我们运行一个不允许共享登录详细信息的网站,但是从未构建系统来阻止这些用户。现在管理层想要一份分享者的报告。我很确定我们可以通过分析我们的统计数据库找到它们。

我检测共享登录的想法是在每个月底查询统计表(MSSQL 2008)并生成嫌疑人列表。为了抓住它们,我需要一个显示“切换”会话/IP地址的查询。

例如,以下是允许的:

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

问题是在查询成千上万的条目时如何有效地做到这一点?

4

1 回答 1

2

注意:我删除了我之前的 CTE 答案,因为我可以使它工作的唯一方法是使用LAGSQL 2008 上不可用的方法。不过,我想出了一些运行速度更快的方法。

下面将数据拆分为两个 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

于 2013-09-05T14:49:02.033 回答