【问题标题】:Select multiple field duplicates from MySQL Database从 MySQL 数据库中选择多个字段重复项
【发布时间】:2018-09-13 12:31:58
【问题描述】:

我有一个旧论坛,其中包含重复的第一篇帖子(可能回复不同)的主题。我想删除除其中一个线程之外的所有线程(保留查看次数最多的线程)。

我有以下 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;

目前,此查询正确地对线程进行分组,但它仅显示随机 thread_id - 而不是与 min(view_count) 对应的 thread_id。

我已经阅读了有关如何解决此问题的信息,但我无法弄清楚如何实现这一点 - 因为它看起来无法通过查询对行进行分组排序。

编辑

感谢 Madhur 的帮助,查询现在返回所有要删除的线程 ID。但是,我可以弄清楚如何删除具有匹配 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); 

【问题讨论】:

  • 能否请您也发布示例数据和预期结果?
  • 检查 stackoverflow.com/a/52314208/2469308 让我知道它是否有效,虽然是一种 hacky 方法,但应该有效!在 MySQL 版本 >= 8.0 中,您可以使用窗口函数轻松实现这一点

标签: mysql duplicates


【解决方案1】:

一个非常老套的解决方案是让thread_idGROUP_CONCAT 中按view_count 排序。然后,我们可以利用字符串操作得到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 

【讨论】:

  • 这可能有点骇人听闻,但这看起来效果很好!非常感谢。有没有办法可以修改查询以删除行,而不是选择它们?我尝试使用“DELETE FROM xf_thread WHERE thread_id IN”删除,然后将其余部分作为子查询,但这真的很慢。
  • 您的删除查询是什么?您可以编辑问题并向其添加子部分。
  • 谢谢,我已经编辑了问题以包含我尝试过的删除查询。
  • @IanCun 子查询会很慢。提示:查看多表连接删除。检查例如:stackoverflow.com/questions/4154707/… 尝试弄清楚。如果还是不行,请告诉我!
  • @IanCun 尝试以下查询: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 &lt; 2 GROUP BY t.title, t.username, p.message HAVING Count(t.title) &gt; 1 AND Count(t.username) &gt; 1 AND Count(p.message) &gt; 1 ORDER BY t.thread_id) AS t_dup ON t_delete.thread_id = t_dup.tid_min_view
猜你喜欢
  • 1970-01-01
  • 2014-02-28
  • 2018-05-06
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
  • 2020-08-03
  • 2011-02-13
  • 1970-01-01
相关资源
最近更新 更多