2011-12-05 40 views
1

我有一个网站,我记录每个链接点击SQL Server 2008数据库中的客户端指标。我已经编写了查询来获得每日总点击量,但是我想知道用户在给定时间范围内点击了多少次(即在5秒内)。每日用TSQL计数?

这里的想法是锁定尝试刮擦内容的传入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 

这一个特别的回报以下错误:

Msg 535, Level 16, State 0, Line 3 The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

所以再次,我想用秒日期部分,其我相信我走在正确的轨道上,但还没有完全实现。

帮助赞赏。谢谢。

- 更新 -

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

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

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

与datediff的问题是它溢出(显然)。您的startdate为0,并且记录了任何日期时间的'ClickTimeStamp'。任何超过约68年的与datepart的时间差(秒)都会有溢出,因为datediff会返回int。有关它的更多信息,请参见:http://stackoverflow.com/questions/1275208/sql-server-datediff-function-resulted-in-an-overflow – king14nyr

+0

该请求也存在逻辑问题。假设你的IP在10:00:00 AM点击,然后在10:00:01和10:00:04之间点击3次。然后在10:00:07再次。您的输出包含(1 + 3)的计数,忽略10:00:07还是1 + 3 + 1,因为10:00:07在10:00:04的5秒内?取决于响应将决定获得结果的方法。 – xQbert

回答

0

为您更新的答案:这个问题是在

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

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

你仍然需要一些类型的时间段,如perahps这样:

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

我有点不舒服使用GETDATE()有 - 如果你有一个具体的日期时间值(精确到秒),你应该使用它。

+0

嗯,我明白了。我试过这个...点击几个链接,运行查询(-5,而不是5),给出0。 – ElHaix

+0

是的,-5,只是修复 –

+0

不得不交换第一个GETDATE()和DATEADD() - 工作。但是,我可以实现相同:: WHERE ClickTimeStamp> dateadd(秒,-5,getdate())::使用“>”和BETWEEN是否有性能差异? – ElHaix

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等)。这可以作为临时表来完成。
  • 对于所有事件,计算出经过的秒数,因为你的最早的点
  • 对于每个桶,数着打的斗事件,通过ip地址分组数(inner join on the temp table on seconds between lowValue and highValue
  • 识别那些超出阈值() ,并对他们进行解密。
+0

这是否意味着用户必须在定义的时间范围内执行5次点击?如果用户点击00:00:02,03,04,05,06怎么办?这不适合于一个桶。我认为他需要自己加入这个 – Twelfth

+0

这就是“滑动窗口”的想法出现的地方。更棘手的是,你必须每秒发生一些事情,并在接下来的5秒内检查它。 (可能但很复杂,这就是为什么我没有拼出来 - 水桶更容易。) –

+0

...然后我读你的帖子,这就是我刚才所说的。我会给它+1,但我们都不能解决他的问题... –

1

希望我的语法好,我只有oracle来测试它。我假设你有一个名为user_id的ID列,该列对用户来说是唯一的(是否user_click_id?有助于在可以的时候在这些问题中包含表创建语句)

您必须执行自我连接在这一个。逻辑将采取userclick并加入userclick userId = userId和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 

此SELECT语句应该给你的每一个相距秒0-5从同一个用户是clicktimestamp记录USER_ID/clicktimestampe和1个排。现在只需要计算所有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机上我的语法....有可能在有一些错字的,但逻辑应该是好。

+0

我看了一下这种方法,当5秒内点击次数<5时,我得到了一堆“......无法绑定”的错误。 – ElHaix

+0

可能是我的语法呢? – Twelfth