Помогите определить спамеров на форуме с помощью SQL-запроса? - PullRequest
6 голосов
/ 15 ноября 2010

Я хотел бы получить простой запрос к базе данных, чтобы получить аномалии во временном интервале, который пользователи публикуют на нашем форуме.Если у меня следующая структура базы данных:

ThreadId | UserId | PostAuthor | PostDate |
1          1000     Spammer      2010-11-14 02:52:50.093
2          1000     Spammer      2010-11-14 02:53:06.893
3          1000     Spammer      2010-11-14 02:53:22.130
4          1000     Spammer      2010-11-14 02:53:37.073
5          2000     RealUser     2010-11-14 02:53:52.383
6          1000     Spammer      2010-11-14 02:54:07.430 

Я хотел бы установить порог, например, чтобы сказать, что если 3 сообщения от одного пользователя попадают в период времени 1 минута, то авторможет спамить на форумах.В свою очередь, я хотел бы вернуть пользователя «Спамер» в запросе с количеством постов, сделанных за отведенное время.

В приведенном выше примере Spammer разместил 4 сообщения в течение периода времени 1 минута, поэтому результат запроса может выглядеть следующим образом:

UserId | PostAuthor | PostCount | DateStart               | DateEnd
1000     Spammer      4           2010-11-14 02:52:50.093   2010-11-14 02:53:37.073

Любые предложения в форматевозвращенные данные наш добро пожаловать.Формат не так важен для меня, как правильное определение нарушителей форума.

Ответы [ 5 ]

1 голос
/ 16 ноября 2010

Решение для самостоятельного соединения:

Select T1.UserId, T1.PostAuthor, T1.PostDate, Max(T2.PostDate), Count(*)
from
  Posts T1 INNER JOIN Posts T2 
  ON T1.UserId = T2.UserId and 
     T2.PostDate between T1.PostDate and dateadd(minute, 1, T1.PostDate)
group by T1.UserId, T1.PostAuthor, T1.PostDate
having count(*) >= 3
1 голос
/ 15 ноября 2010

Не все, что вы хотели в выводе, но это начало:

(Reword: дать мне все сообщения, для которых после него существует 2 или более других сообщений, но в течение одной минуты)

Select 
  Spammer = PostAuthor,
  NumberOfPosts = (Select Count(*) 
                   From Posts As AllPosts 
                   Where AllPosts.UserID = Posts.UserID)
From Posts
Where 2 <= (Select Count(*)
            From Posts As OtherPosts
            Where OtherPosts.UserID = Posts.UserID
              And OtherPosts.PostDate > Posts.PostDate
              And OtherPosts.PostDate < DateAdd(Minute, 1, Posts.PostDate))
0 голосов
/ 15 ноября 2010

Я верю, что Садхир на правильном пути.У меня есть несколько исправлений к сценарию.Первая коррекция включает использование единиц измерения DATADIFF «минуты».Использование минуты не вернет четыре записи из примера Джорджа.Я изменил «минуты» на «секунды».Я также отформатировал вывод, чтобы показать количество записей, записанных в течение минуты, вычислив разницу между количествами в CTE.Хотя Джордж не просил об этом, я добавил параметр для контроля количества дней, чтобы просмотреть таблицу, так как я не думал, что кто-то захочет делать всю таблицу каждый раз.

DECLARE @threshold INT; 
SET @threshold = 3; 
DECLARE @lookbackdays int;
SET @lookbackdays = 2;

;WITH postCTE as 
( 
SELECT  
    Userid, 
    PostAuthor, 
    PostDate, 
    RowNumber = ROW_NUMBER() OVER (ORDER BY UserId,PostDate ASC) 
FROM 
    Post2Forum 
WHERE 
    PostDate > GETDATE() - @lookbackdays
) 
SELECT  
    p1.PostAuthor AS [PostAuthor],  
    p2.RowNumber - p1.RowNumber +1 AS [PostCount],
    p1.UserId,  
    p1.PostDate AS [DateStart],  
    p2.PostDate AS [DateEnd] 
FROM 
    postCTE p1 
INNER JOIN 
    postCTE p2  
    ON p1.UserId = p2.UserId  
    AND p1.Rownumber = p2.RowNumber - (@threshold ) 
WHERE 
    DATEDIFF(second,p1.PostDate,p2.PostDate) <= 60

Результатзапрос в моем тестировании:

PostAuthor PostCount UserId                   DateStart            DateEnd
Spammer           4   1000 2010-11-14 02:52:50.093  2010-11-14 02:53:37.073
0 голосов
/ 15 ноября 2010

Я попробовал свои силы в этом и придумал это (я думаю, это дает почти такой же результат, как у Стю, хотя и по количеству сообщений). Это идентифицирует пользователей, у которых есть 3 сообщения в течение 1 минуты (так, в случае 5 сообщений, это повторяет пользователя 3 раза)

DECLARE @threshold INT;
SET @threshold = 3;

;WITH postCTE as
(
SELECT 
  Userid,
  PostAuthor,
  PostDate,
  RowNumber = ROW_NUMBER() OVER (PARTITION by UserId ORDER BY PostDate ASC)
FROM Posts
)
SELECT 
  p1.UserId, 
  p1.PostAuthor, 
  p1.PostDate AS StartTime, 
  p2.PostDate AS EndTime
FROM postCTE p1
   JOIN postCTE p2 
     ON p1.UserId = p2.UserId 
     AND p1.Rownumber = p2.RowNumber - (@threshold - 1)
WHERE DATEDIFF(MINUTE,p1.PostDate,p2.PostDate) <= 1

Возвращает следующий набор результатов

UserId   PostAuthor  StartTime                EndTime
1000    Spammer    2010-11-14 02:52:50.093  2010-11-14 02:53:22.130
1000    Spammer    2010-11-14 02:53:06.893  2010-11-14 02:53:37.073
1000    Spammer    2010-11-14 02:53:22.130  2010-11-14 02:54:07.430
0 голосов
/ 15 ноября 2010

Не совсем то, что вы хотите, но послужит цели более или менее ...

SELECT 
  UserId, 
  PostAuthor, 
  COUNT(*) AS [PostCount],
  YEAR(PostDate), 
  MONTH(PostDate), 
  DAY(PostDate), 
  DATEPART(hh, PostDate), 
  DATEPART(mi, PostDate)
FROM LogTable
GROUP BY 
  UserId, 
  PostAuthor, 
  YEAR(PostDate), 
  MONTH(PostDate), 
  DAY(PostDate), 
  DATEPART(hh, PostDate), 
  DATEPART(mi, PostDate)
HAVING COUNT(*) >= 3
ORDER BY 
  YEAR(PostDate), 
  MONTH(PostDate), 
  DAY(PostDate), 
  DATEPART(hh, PostDate), 
  DATEPART(mi, PostDate)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...