首先,您的要求可以用多种方式解释,所以让我统计一下我认为您想要什么...我认为您是说当给定 IP 地址有 30 分钟不活动时会话结束。因此,如果一个 IP 地址每分钟访问一个站点 2 小时,然后休息 30 分钟,这代表一个会话。假设这是你的意图......
您可以使用 LEAD 和 LAG 来帮助您识别会话。我的测试数据由一个 Id 列、一个 IPAddress 列和一个 Created 列组成。这是代码,解释如下...
WITH t1 AS
(
SELECT
*
, DATEDIFF(minute, LAG(Created, 1, 0) OVER (PARTITION BY IPAddress ORDER BY Created), [Created]) AS SinceLastAccess
FROM
IISLog
), sessionStarts AS
(
SELECT
*
FROM
t1
WHERE
SinceLastAccess >= 30
), sessionInfo AS
(
SELECT
IPAddress
, Created AS SessionStart
, LEAD(Created, 1, '2025-01-01') OVER (PARTITION BY IPAddress ORDER BY CREATED) AS SessionEnd
FROM
sessionStarts
)
SELECT * FROM sessionInfo
第一个 CTE (t1) 选择数据,但添加了一个名为 的列SinceLastAccess
。这个新列使用 LAG 函数查看前一行中的值并计算已经过去了多少分钟。将此计算PARTITION BY
限制到每个 IP 地址。
第二个 CTE (sessionStarts) 只是从 t1 中选择SinceLastAccess
值大于 30 的那些行。这有效地告诉我们每个会话的开始。
最后,`sessionInfo' CTE 建立在第二个之上。使用 LEAD 函数,我们期待看到下一个会话从哪里开始。该值被认为是当前行的会话结束时。我们最终得到的是一个 IP 地址、会话开始和会话结束。现在你有了这些,应该很容易将它加入原始表并将其分组。