1

我有一个网站,在其中记录每个单击链接的 SQL Server 2008 数据库中的客户端指标。我已经编写了查询以获取每日总点击次数,但是我想了解用户在给定时间跨度内(即 5 秒内)点击了多少次。

这里的想法是锁定试图抓取内容的传入 IP 地址。假设在 5 秒内检测到超过 5 次“点击”或来自给定 IP 地址的每日点击次数超过某个值,则认为这是一次抓取尝试。

我尝试了以下几种变体:

-- when a user clicked more than 5 times in 5 seconds
SELECT DATEADD(SECOND, DATEDIFF(SECOND, 0, ClickTimeStamp), 0) as ClickTimeStamp, COUNT(UserClickID) as [Count]
FROM UserClicks
WHERE DATEDIFF(SECOND, 0, ClickTimeStamp) = 5
GROUP BY IPAddress, ClickTimeStamp

这一个特别返回以下错误:

消息 535,级别 16,状态 0,第 3 行 datediff 函数导致溢出。分隔两个日期/时间实例的日期部分的数量太大。尝试将 datediff 与不太精确的日期部分一起使用。

所以再一次,我想使用秒日期部分,我相信我在正确的轨道上,但不太明白。

帮助表示赞赏。谢谢。

- 更新 -

很好的建议,帮助我认为这种方法是错误的。每次点击都会进行检查。我应该做的是对于给定的时间戳,检查在最后 5 秒内是否记录了来自同一 IP 地址的 5 次点击。所以它就像,计算 > GetDate() - 5 秒的点击次数

尝试以下仍然不能给我一个准确的数字。

SELECT COUNT(*)
FROM UserClicks
WHERE ClickTimeStamp >= GetDate() - DATEADD(SECOND, -5, GetDate())
4

3 回答 3

1

希望我的语法很好,我只有 oracle 来测试它。我将假设您有一个名为 user_id 的 ID 列,该列对于该用户是唯一的(它是 user_click_id 吗?如果可以的话,在这些问题中包含表创建语句很有帮助)

您必须对此进行自我加入。逻辑将采用 userclick 并在 userId = userId 上加入 userclick,并且 clicktimestamp 的差异在 0-5 秒之间。然后它从子选择开始计数。

select u1.user_id, u1.clicktimestamp, u2.clicktimestamp
from userclicks uc1
left join user_clicks uc2  
    on u2.userk_id = u1.user_id
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) <= 5
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) > 0

此选择语句应该为您提供 user_id/clicktimestamp 和 1 行,用于与来自同一用户的 clicktimestamp 相距 0 到 5 秒之间的每条记录。现在只需计算所有 user_id,u1.clicktimestamp 组合并突出显示 5 或更多的组合。获取上述查询并将其转换为子选择并从中提取计数:

select u1.user_id, u1.clicktimestamp, count(1)
from 
(select u1.user_id, u1.clicktimestamp
from userclicks uc1
left join user_clicks uc2  
    on u2.userk_id = u1.user_id
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) <= 5
    and datediff(second,u1.ClickTimeStamp,u2.ClickTimeStamp) > 0) a
group by u1.user_id, u1.clicktimestamp
having count(1) >= 5

希望我可以在 MS 机器上验证我的语法……那里可能有一些错字,但逻辑应该是好的。

于 2011-12-05T19:24:54.667 回答
0

假设只为当前活动输入日志条目——也就是说,每当插入新行时,记录的时间是那个时间点,而不是任何以前的时间点——那么你应该只需要查看数据设定时间段,而不必像现在一样查看“所有数据”。

下一个问题是:您多久进行一次检查?如果您关心每秒点击次数,那么“每小时一次”和“每 24 小时一次”之间的内容似乎是合理的。

下一步:定义你的间隔。“5 秒内每个 IPAddress 的所有点击”可以有两种方式:设置窗口(00-04、05-09、10-14 等)或滑动窗口(00-04、01-05、02-06 等)。 ) 可能与 5 秒的窗口无关,但可能与更长的时间段更相关(每“天”的点击次数)。

有了这个,我会采取的一般方法是:

  • 从您关心的最早时间点开始(1 小时前、24 小时前)
  • 设置“桶”,表示可以识别时间窗口(00:00:00 - 00:00:04、00:00:05 - 00:00:09 等)。这可以作为临时表来完成。
  • 对于所有事件,计算自最早点以来经过的秒数
  • 对于每个存储桶,计算命中该存储桶的事件数,按 IPAddress ( inner join on the temp table on seconds between lowValue and highValue)分组
  • 识别那些超过您的阈值 ( having count(*) > X) 的人,并为他们开窗。
于 2011-12-05T18:48:32.357 回答
0

更新的答案:问题出在第三行

SELECT COUNT(*)
 FROM UserClicks
 WHERE ClickTimeStamp >= GetDate() - DATEADD(SECOND, -5, GetDate()) 

GetDate() - DATEADD(SECOND, -5, GetDate())是说“取当前日期时间并减去(当前日期时间减去五秒)”。我不完全确定这会产生什么样的价值,但它不会是你想要的。

您仍然需要某种时间段,例如:

SELECT count(*)
 from UserClicks
 where IPAddress = @IPAddress
  and ClickTimeStamp between getdate() and dateadd(second, -5, getdate())

我在那里使用 getdate() 有点不舒服——如果你有一个特定的日期时间值(精确到秒),你可能应该使用它。

于 2011-12-05T22:48:35.893 回答