这对我来说已经是上周的烦恼了,凭借基本的知识,我根本无法找到能够把我们带到我们需要的地方的解决方案。我已经搜索过更新,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 ;
在连接所需的值之后,我们如何创建删除重复项的(UPDATE
或DELETE
)查询?因为,使用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`;
答案 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;
答案 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()结果。