【问题标题】:Mysql Query to delete duplicatesMysql查询删除重复项
【发布时间】:2012-06-05 08:25:52
【问题描述】:

我有重复的结果,如下所示,其中某些列可能有数据但可能没有

| contact_info | icon | id  | title         | lastmodified_by  |
+--------------+------+-----+---------------+------------------+
|          169 |  305 | 123 | Whakarewarewa | 2011100400305262 |
|         NULL | NULL | 850 | Whakarewarewa | NULL             |
+--------------+------+-----+---------------+----------------



| contact_info | icon | id  | title         | lastmodified_by  |
+--------------+------+-----+---------------+------------------+
|         NULL | NULL | 123 | Paris         | NULL             |
|         NULL | NULL | 850 | Paris         | NULL             |
+--------------+------+-----+---------------+----------------

我想删除数据较少的记录,如果所有字段值完全相同,则删除任何行。 这样的记录有上千条。

【问题讨论】:

  • 很明显会有多条记录,否则我不会在stackoverflow上问这个问题。
  • 这个问题被问了数万亿次,hereherehereherehere...
  • 这个问题与所有问题不同。这里有 3 种情况 1) 列具有完全相同的数据 2) 一列有数据而另一列没有。 3) 不能删除所有最小 id 或最大 id,因为数据可以是最大 id 或最小 id
  • @lorenzo-s 此链接描述了如何删除重复项,但不考虑 NULL 值 - '记录数据较少'。
  • @saunjean 好的,但至少你可以从这些答案开始尝试一些东西,然后将你的代码与问题一起发布。

标签: mysql


【解决方案1】:

试试这个两步解决方案:

运行此查询以查看所有重复项 - 数据较少的记录 -

SELECT t1.* FROM table t1
  JOIN (
    SELECT
      title,
      MIN(IF(contact_info IS NULL, 0, 1) + IF(contact_info IS NULL, 0, 1) + IF(lastmodified_by IS NULL, 0, 1)) min_value_data,
      MAX(IF(contact_info IS NULL, 0, 1) + IF(contact_info IS NULL, 0, 1) + IF(lastmodified_by IS NULL, 0, 1)) max_value_data
    FROM table GROUP BY title HAVING min_value_data <> max_value_data
  ) t2
  ON t1.title = t2.title AND IF(t1.contact_info IS NULL, 0, 1) + IF(t1.contact_info IS NULL, 0, 1) + IF(t1.lastmodified_by IS NULL, 0, 1) <> t2.max_value_data

将其改写为DELETE语句并执行。


然后运行此查询以删除除最小 ID 之外的所有重复项:

DELETE t1 FROM table t1
  JOIN (SELECT MIN(id) id, title FROM table GROUP BY title) t2
    ON t1.id <> t2.id AND t1.title = t2.title;

【讨论】:

  • 如果任何具有 min id 的记录没有数据但 max id 中有数据怎么办。它将删除具有最大 id 的 id 并保留具有最小 id 的 id???
  • 是的,你是对的。我读了你编辑的问题;并且应该重写查询。
  • 它给出了这个 "ERROR 1052 (23000): Column 'title' in field list is ambiguous" 。然后我想把 t1.title 放在查询的开头,但是它给出了“ERROR 1054 (42S22): Unknown column 't1.value_data' in 'on Clause'”
  • 添加表别名(字段应为t1.title)。
  • 我在发表评论之前尝试了同样的事情,但错误仍然相同“错误 1054 (42S22): Unknown column 't1.value_data' in 'on Clause'”
【解决方案2】:

使用它来选择重复项,随意将其更改为删除语句:

SELECT * FROM `test`,
(SELECT title, count( title ) AS ttl
FROM `test`
GROUP BY title
HAVING ttl >1) AS sub

WHERE test.title = sub.title
AND contact_info IS NULL AND lastmodified_by IS NULL 

【讨论】:

  • 此查询在 Where title=Paris 的情况下失败。它在结果中列出了巴黎。在这种情况下,两个结果都是完全重复的,包括所有字段
  • 正确,我没有看到您的巴黎示例。怎么样:显示第 0 - 1 行(共 2 行,查询耗时 0.0007 秒) SELECT * FROM test AS main, ( SELECT title, count( title ) AS ttl FROM test GROUP BY title HAVING ttl >1 ) AS sub WHERE main.title = sub.title AND main.contact_info IS NULL AND main.lastmodified_by IS NULL GROUP BY main.contact_info, main.icon, main.title, main.lastmodified_by
  • 这个查询几乎是正确的,除了不能在子查询中引用要修改或删除行的表的部分。所以我不能使用这个查询删除
  • 在下面查看我的新答案。使用更多查询。
【解决方案3】:

主表 = tes1

创建温度

创建临时表 my_temp (id INT(20) NOT NULL) ENGINE=MEMORY;

填写要删除的id

INSERT INTO my_temp (id) SELECT id FROM tes1 AS main, (SELECT title, count(title) AS ttl FROM tes1 GROUP BY title HAVING ttl >1 ) AS sub WHERE main.title = sub.title AND main.contact_info 为 NULL 且 main.lastmodified_by 为 NULL GROUP BY main.contact_info、main.icon、main.title、main.lastmodified_by;

删除!

DELETE FROM tes1 WHERE id IN(从 my_temp 中选择 id);

清理,注意:我们真的需要这个吗?

删除表 my_temp;

【讨论】:

    猜你喜欢
    • 2011-03-23
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多