concat字段具有共同的重复键并删除那些留下一个的dupes

时间:2016-06-10 21:44:10

标签: mysql database duplicates concatenation mysql-workbench

这对我来说已经是上周的烦恼了,凭借基本的知识,我根本无法找到能够把我们带到我们需要的地方的解决方案。我已经搜索过更新,group_concat,concat,join,但我无法得到我们需要的结果。

问题如下:

我们有2个列可供使用,以获得我们需要的结果:

我们正在努力的数据库:

+------------------------------------+-------------+  
| id                                 | value       |  
+------------------------------------+-------------+  
|  D44172cb5c086c19a4c0286270916bc52 | A           |  
|  D44172cb5c086c19a4c0286270916bc52 | C           |  
|  D44172cb5c086c19a4c0286270916bc52 | B           |  
|  D87d93570cbc9a3edc18601e0aff6e261 | D           |  
|  D87d93570cbc9a3edc18601e0aff6e261 | A           |
|  D87d93570cbc9a3edc18601e0aff6e261 | F           |
+------------------------------------+-------------+ 

我们期望获得:

 +-------------------------------------+-------------+  
 | id                                  | value       |  
 +-------------------------------------+-------------+  
 |  D44172cb5c086c19a4c0286270916bc52  | A|C|B       |  
 |  D87d93570cbc9a3edc18601e0aff6e261  | D|A|F       |  
 +-------------------------------------+-------------+ 

我们目前正在使用一个有效的SELECT命令,并且在一个名为valuenew的临时(因为我们只选择)列中提供了预期的数据:

SELECT * GROUP_CONCAT(value SEPARATOR '|') AS valuenew FROM db.table GROUP BY id ;

在连接所需的值之后,我们如何创建删除重复项的(UPDATEDELETE)查询?因为,使用GROUP_CONCAT返回的行数将小于实际存在的行数。

我们需要在稍后阶段将连接值与其他列组合在一起,这样行才需要等于返回的行。

CREATE TABLE IF NOT EXISTS `temp` 
SELECT *, GROUP_CONCAT(`value` SEPARATOR '|') AS `values`
FROM `db`.`table` 
GROUP BY `id`;

TRUNCATE TABLE `db`.`table`;

UPDATE `temp` SET value = values;
ALTER TABLE `temp` DROP COLUMN values;

INSERT INTO `db`.`table`([all column titles here])
SELECT * 
FROM `db`.`temp`
;

DROP TABLE `db`.`temp`;

2 个答案:

答案 0 :(得分:1)

创建一个生成连接值的视图,而不是更新表。

CREATE VIEW yourtable_view
SELECT id, GROUP_CONCAT(value ORDER BY value SEPARATOR '|') AS values
FROM yourtable
GROUP BY id;

然后在需要使用非规范化值的查询中使用此视图。

如果您真的需要按照自己的方式进行操作,那么您的表需要每个组中的另一列可用于区分行,因此我们可以更新组中的第一行并删除其余的行;如果您有auto_increment列,则可以使用它。我在下面打电话给unique_id

-- First add the concatenated values to the first row in each group
UPDATE yourTable AS t1
JOIN (SELECT id, MIN(unique_id) AS first_id, GROUP_CONCAT(value ORDER BY value SEPARATOR '|') AS newvalues
      FROM yourTable
      GROUP BY id
      HAVING COUNT(*) > 1) AS t2
ON t1.id = t2.id AND t1.unique_id = t2.first_id
SET t1.value = t2.values;

-- Then delete all the remaining rows in each group
DELETE t1.*
FROM yourTable AS t1
JOIN (SELECT id, MIN(unique_id) AS first_id
      FROM yourTable
      GROUP BY id
      HAVING COUNT(*) > 1) AS t2
ON t1.id = t2.id AND t1.unique_id > t2.first_id;

DEMO

答案 1 :(得分:1)

如果你真的必须这样做,这可能是最直接的做法。

CREATE TABLE `db`.`temp`
SELECT `id`, GROUP_CONCAT(`value` SEPARATOR '|') AS `value`
FROM `db`.`table` 
GROUP BY `id`;

TRUNCATE TABLE db.table;

INSERT INTO `db`.`table`(`id`, `value`)
SELECT `id`, `value` 
FROM `db`.`temp`
;

DROP TABLE `db`.`temp`

当然,如果还有其他字段,您必须适当考虑它们以防止数据丢失。 您还可以将temp表设为真TEMPORARY表,但如果您在截断和重新插入之间失去连接,则会丢失所有数据。

编辑:同时确保value字段可以保存最长的GROUP_CONCAT()结果。