Формула SQL для MySQL таблицы - PullRequest
0 голосов
/ 05 декабря 2018

Привет - у меня есть таблица БД (MySQL ver 5.6.41-84.1-log), в которой содержится около 92 000 записей со столбцами для:

  • id (добавочный уникальный)ID)
  • post_type (не важно)
  • post_id (не важно, но показывает отношение к другой таблице)
  • user_id (не важно)
  • голос ((не важно)
  • ip (IP-адрес, т. е. 123.123.123.123)
  • проголосовал (метка даты по Гринвичу, т. е. 2018-12-03 04:50:05)

Недавно я провел конкурс, и у нас было правило, что ни один IP не может голосовать более 60 раз в день.Так что теперь мне нужно запустить пользовательскую формулу SQL, которая применяет следующее правило:

Для каждого IP-адреса, для каждого дня, если есть> 60 строк, удалите эти дополнительные строки.

Спасибо за помощь!

Ответы [ 3 ]

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

Вы можете подойти к этому, значительно упростив пример данных и используя имитацию номера строки для версии mysql до 8.0 или оконную функцию для версий 8.0 или выше.Я предполагаю, что вы не на версии 8 или выше в следующем примереудаление нескольких таблиц удаляет из t, соединенного с, чтобы дать

+----+------+
| id | ip   |
+----+------+
|  1 | 1    |
|  2 | 1    |
|  3 | 3    |
|  4 | 3    |
|  5 | 2    |
|  9 | 2    |
+----+------+
6 rows in set (0.00 sec)
0 голосов
/ 07 декабря 2018

Мне кто-то помог мне написать следующий запрос, который отвечал на мой вопрос.

SET SQL_SAFE_UPDATES = 0;
create table temp( SELECT id, ip, voted
    FROM
        (SELECT id, ip, voted,
            @ip_rank := IF(@current_ip = ip, @ip_rank + 1, 1) AS ip_rank,
            @current_ip := ip
        FROM `table_name` where ip in (SELECT ip from `table_name` group by date(voted),ip having count(*) >60)
        ORDER BY ip, voted desc
        ) ranked
    WHERE ip_rank <= 2);
DELETE FROM `table_name`
WHERE id not in (select id from temp) and ip in (select ip from temp);
drop table temp;
0 голосов
/ 05 декабря 2018

Это сложный вопрос, и я думаю, что трудно дать 100% надежный ответ без фактической таблицы и данных, с которыми можно поиграть.

Однако позвольте мне попытаться описать логику и составить запрос.шаг за шагом, так что вы можете поиграть с ним и, возможно, исправить скрытые ошибки.

1) Мы начнем с выбора всех IP-адресов, которые отправили более 60 голосов в определенный день.Для этого мы используем group by в день голосования и на IP-адресе в сочетании с having предложением

select date(voted), ip_adress
from table 
group by date(voted), ip_adress 
having count(*) > 60

2) С этого момента мы возвращаемся к таблице и выбираем первые 60идентификаторы, соответствующие каждому дню голосования / паре IP-адресов.id является автоинкрементным полем, поэтому мы просто сортируем, используя это поле и используя инструкцию mysql limit

    select id, ip_adress, date(voted) as day_voted
    from table 
    where ip_adress, date(voted) in (
        select date(voted), ip_adress 
        from table 
        group by date(voted), ip_adress 
        having count(*) > 60
    ) 
    order by id
    limit 60

3) Наконец, мы снова возвращаемся к таблице и ищем все идентификаторычей ip адрес и день голосования принадлежат приведенному выше списку, но чей идентификатор больше максимального идентификатора списка.Это достигается с помощью join и требует условия group by.

select t1.id 
from 
    table t1
    join (      
        select id, ip_adress, date(voted) as day_voted 
        from table 
        where ip_adress, date(voted) in (
            select date(voted), ip_adress 
            from table
            group by date(voted), ip_adress
            having count(*) > 60
        )
        order by id
        limit 60
    ) t2 
        on t1.ip_adress = t2.ip_adress 
        and date(t1.voted) = t2.day_voted and t1.id > max(t2.id)
group by t1.id

Это должно вернуть список всех идентификаторов, которые нам нужно удалить.Проверьте, прежде чем идти дальше.

4) Самый последний шаг - удалить эти идентификаторы.В mysql есть ограничения, из-за которых delete с условием подзапроса сделать довольно непросто.См. следующий вопрос SO для получения дополнительной информации о технической подготовке.Вы можете использовать временную таблицу для хранения выбранных идентификаторов или попытаться перехитрить mysql, заключив в подзапрос и присвоив ему псевдонимы.Давайте попробуем второй вариант:

delete t.* from table t where id in ( select id from (
    select t1.id 
    from 
        table t1
        join (      
            select id, ip_adress, date(voted) as day_voted 
            from table 
            where ip_adress, date(voted) in (
                select date(voted), ip_adress
                from table 
                group by date(voted), ip_adress
                having count(*) > 60
            )
            order by id
            limit 60
        ) t2 
            on t1.ip_adress = t2.ip_adress
            and date(t1.voted) = t2.day_voted
            and t1.id > max(t2.id)
    group by t1.id
) x );

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...