Выберите несколько дубликатов полей из базы данных MySQL - PullRequest
0 голосов
/ 13 сентября 2018

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

У меня есть следующий запрос SQL, чтобы помочь идентифицировать дубликаты потоков, но я не могу найти способ для этогосписок только дублирует с самым низким значением для столбца xf_thread.view_count:

SELECT
    t.thread_id, MIN(t.view_count)
FROM
    xf_thread t
INNER JOIN
    xf_post p ON p.thread_id = t.thread_id
WHERE
    t.first_post_id = p.post_id
GROUP BY
    t.title,
    t.username,
    p.message
HAVING
    COUNT(t.title) > 1
    AND COUNT(t.username) > 1
    AND COUNT(p.message) > 1;

В данный момент этот запрос правильно группирует потоки, но он показывает только случайный идентификатор_потока - вместо идентификатора_потока, соответствующего значению min (view_count)).

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

edit

Благодаря помощи Madhur, запрос теперь возвращает все идентификаторы потоков, которые должны быть удалены.Тем не менее, я могу выяснить, как удалить строки с соответствующими идентификаторами thread_id.Вот запрос, который я пытался использовать (он просто продолжает работать, тогда как запрос на выборку (https://stackoverflow.com/a/52314208/2469308) выполняется за секунды:

DELETE FROM xf_thread 
WHERE  thread_id IN (SELECT Substring_index(Group_concat(DISTINCT t.thread_id 
                                            ORDER BY 
                                            t.view_count 
                                                                ASC 
                                            SEPARATOR ','), 
                                   ',', 1) AS 
                            thread_id_with_minimum_views 
                     FROM   (SELECT * 
                             FROM   xf_thread) t 
                            INNER JOIN xf_post p 
                                    ON p.thread_id = t.thread_id 
                     WHERE  t.first_post_id = p.post_id 
                            AND t.user_id = 0 
                            AND t.reply_count < 2 
                     GROUP  BY t.title, 
                               t.username, 
                               p.message 
                     HAVING Count(t.title) > 1 
                            AND Count(t.username) > 1 
                            AND Count(p.message) > 1 
                     ORDER  BY t.thread_id); 

1 Ответ

0 голосов
/ 13 сентября 2018

Очень хакерское решение - отсортировать thread_id по view_count в GROUP_CONCAT . Затем мы можем использовать строковые операции, чтобы получить thread_id с минимумом view_count.

В вашем предложении SELECT вместо t.thread_id вы можете попробовать следующее:

SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT t.thread_id 
                             ORDER BY t.view_count ASC 
                             SEPARATOR ','), 
                ',', 
                1) AS thread_id_with_minimum_views

Теперь, основываясь на запросе SELECT для определения дубликатов записей с минимальным представлением, запрос DELETE на удаление таких записей из таблицы xf_thread будет выглядеть следующим образом:

DELETE t_delete FROM xf_thread AS t_delete 
INNER JOIN (SELECT CAST(SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT t.thread_id ORDER BY t.view_count ASC SEPARATOR ','), ',', 1) AS UNSIGNED) AS tid_min_view 
            FROM (SELECT * FROM xf_thread) t 
            INNER JOIN xf_post p ON p.thread_id = t.thread_id 
            WHERE t.first_post_id = p.post_id 
              AND t.user_id = 0 
              AND t.reply_count < 2 
            GROUP BY t.title, t.username, p.message 
            HAVING Count(t.title) > 1 
               AND Count(t.username) > 1 
               AND Count(p.message) > 1 
            ORDER BY t.thread_id) AS t_dup 
  ON t_delete.thread_id = t_dup.tid_min_view 
...