【问题标题】:Renaming the duplicate data in sql重命名sql中的重复数据
【发布时间】:2011-09-14 12:46:05
【问题描述】:

我可以使用这个查询找出重复的数据

   SELECT names FROM group GROUP BY names HAVING count(*) > 1

我能够得到重复的数据。我只需要知道如何将这个重复的数据重命名为 new

  INPUT
+-----------------+               
| names           |
+-----------------+
| text1           |
| text2           |
| text3           |
| text1           |
| text3           |
| text4           |
+-----------------+

OUTPUT  
+-----------------+
| names           |
+-----------------+ 
| text1           |
| text2           |
| text3           |
| text1 new value |->RENAMED
| text3 new value |->RENAMED
| text4           |
+-----------------+

【问题讨论】:

  • 您想如何重命名它?
  • 像添加新的名字一样
  • 如果有超过 on duplicate 会发生什么?添加新的会将重复项减少 1,然后仍然有一些重复项(添加了新项)会在您的数据中...
  • 是的,它会减少重复并重命名为该名称以及新的

标签: mysql sql


【解决方案1】:

假设您在表上有某种主键,例如自动递增 id,您可以执行以下操作。

UPDATE group 
SET names = CONCAT(names,' Copy 1')
WHERE ID IN
(
SELECT MAX(ID) 
FROM group 
GROUP BY names 
HAVING count(*) > 1
);

为了解释,它会找到任何有重复的东西,为该集合中的任何东西选择最大 ID,并将“副本 1”附加到它的末尾。如果您使用某些名称 3 次或更多次,您可能仍会留下一些重复项。再次运行它,这次使用“副本 2”而不是“副本 1”。不断重复这个过程,直到你摆脱所有的重复。

更新。要从 @Yahia 借用一个想法并使用 UUID,如果您想在一个查询中完成所有操作,可以执行以下操作。

UPDATE group 
SET names = CONCAT(names, CONCAT ( ' Copy ', UUID_SHORT() ) )
WHERE 
ID NOT IN
(
SELECT MIN(ID) 
FROM group 
GROUP BY names 
HAVING count(*) > 1
) AND
ID IN
(
SELECT ID
FROM group AS G1
INNER JOIN group AS G2
ON G1.names = G2.names AND G1.ID <> G2.ID
);

【讨论】:

  • 也适用于 sql server,只需将 UUID_SHORT() 替换为 NEWID()。非常好的解决方案! +1
  • 如果您收到错误 1093 - 无法在 FROM 子句中指定要更新的目标表,请参阅stackoverflow.com/a/45498/203915 以了解解决方法
【解决方案2】:

使用(根据评论更正)

UPDATE Group 
SET Names = CONCAT(Names, CONCAT ( ' Copy ', UUID_SHORT() ) )
WHERE 
ID NOT IN
(
SELECT MIN(ID) 
FROM group 
GROUP BY names 
HAVING count(*) > 1
) AND
ID IN
(
SELECT ID
FROM group 
GROUP BY names 
HAVING count(*) > 1
);

这通过连接一个唯一的 UUID_SHORT 使所有重复项在一次执行中唯一...除了具有最小 ID 的那个 - 它保持不变...

【讨论】:

  • 不在 Max(ID) 集中的 ID 怎么办?这个查询很像我的,因为它必须运行多次,每次获取 Max(ID) 是什么。 NOT IN 部分实际上是多余的,因为您只获取了 MAX id。
  • 如何将第二个 IN 部分更改为: AND names IN ( SELECT names FROM group GROUP BY names HAVING count(*) > 1 );
  • @H-Man2 可以工作...不确定这种变化是否足够
  • 实际上,这是行不通的,因为您是按名称分组的,所以它不会拾取所有 ID,而是从每组匹配名称中随机(可能是第一个)id。 MySQL 在这方面是独一无二的,因为它允许您选择未包含在分组中的列,而不是聚合。大多数其他数据库不允许这样做,因为在同一数据上多次运行时结果值不一致。
  • @Kibee 你是对的 - 按照 H-Man2 的建议更改 IN 是行不通的,除非其中包含一些“怪物加入”...
【解决方案3】:

试试这个 -

UPDATE table1 n 
  JOIN (SELECT names FROM table1 GROUP BY names HAVING count(*) > 1) d
    ON n.names = d.names
SET n.names = 'new value';

编辑:

完整代码-

CREATE TABLE table1(
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  names VARCHAR(255) DEFAULT NULL
);    

INSERT INTO table1 VALUES 
  ('text1'),
  ('text2'),
  ('text3'),
  ('text1'),
  ('text3'),
  ('text4');

UPDATE table1 n 
  JOIN (SELECT names, MIN(id) min_id FROM table1 GROUP BY names HAVING COUNT(*) > 1) d
    ON n.names = d.names AND n.id <> d.min_id
SET n.names = CONCAT(n.names, ' new value');

SELECT * FROM table1;

+----+-----------------+
| id | names           |
+----+-----------------+
|  1 | text1           |
|  2 | text2           |
|  3 | text3           |
|  4 | text1 new value |
|  5 | text3 new value |
|  6 | text4           |
+----+-----------------+

【讨论】:

  • 如输出所示,我们怎样才能只替换一个重复名称的新值
  • 好的。在这种情况下,我们应该添加唯一字段来识别记录。我改变了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
  • 2011-12-04
  • 2018-01-27
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
相关资源
最近更新 更多