Ежедневные счета с TSQL? - PullRequest
       33

Ежедневные счета с TSQL?

1 голос
/ 05 декабря 2011

У меня есть сайт, где я записываю клиентские метрики в базе данных 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 секунд зарегистрировано 5 щелчков с того же IP-адреса.Так что это будет что-то вроде: посчитайте количество кликов для> GetDate () - 5 секунд

Попытка выполнить следующее все равно не даст мне точную цифру.

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

Ответы [ 3 ]

1 голос
/ 05 декабря 2011

Надеюсь, мой синтаксис хорош, у меня есть только оракул, чтобы проверить это.Я собираюсь предположить, что у вас есть столбец идентификатора с именем user_id, который уникален для этого пользователя (действительно ли он user_click_id? Полезно ли включать в эти вопросы операторы создания таблиц, когда это возможно)

Вам придется предварительно сформироватьЯ присоединяюсь к этому.Логика будет состоять из щелчка пользователя и присоединения к клику пользователя по userId = userId, а разница по отметке времени клика составляет 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 / clicktimestampe и 1 строку для каждой записи, которая находится на расстоянии от 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 ... там могут быть некоторые опечатки, но логикадолжно быть хорошо.

0 голосов
/ 06 декабря 2011

Ответ для вашего ОБНОВЛЕНИЯ: проблема в третьей строке

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

GetDate() - DATEADD(SECOND, -5, GetDate()) гласит «возьмите текущую дату и вычтите (текущая дата и время минус пять секунд)».Я не совсем уверен, какую ценность это дает, но это будет не то, что вам нужно.

Вам все еще нужен какой-то период времени, perahps, например:

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

Мне немного неудобно использовать там getdate () - если у вас есть конкретное значение даты-времени (с точностью до секунды), вам, вероятно, следует его использовать.

0 голосов
/ 05 декабря 2011

Предполагая, что записи журнала вводятся только для текущей активности - то есть, когда вставляется новая строка, зарегистрированное время относится к этому моменту времени, а не к любому предыдущему моменту времени - тогда вам нужно только просмотреть данные за определенный период времени, и вам не нужно просматривать «все данные», как вы делаете сейчас.

Следующий вопрос: как часто вы делаете эту проверку? Если вас беспокоит количество кликов в секунду, то что-то между «один раз в час» и «один раз в 24 часа» кажется разумным.

Далее: определите свой интервал. «Все клики на IP-адрес в течение 5 секунд» могут идти двумя способами: установить окно (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)
  • Определите те, которые превышают ваш порог (having count(*) > X), и отмените их защиту.
...