我有一个计数表,我希望能够在重命名其中一个复合键字段时对计数求和。这很难解释,所以让我给你看一些SQL:
示例表:
CREATE TABLE `test` (
`id` int(11) NOT NULL,
`type` int(11) NOT NULL,
`count` int(11) NOT NULL,
PRIMARY KEY (`id`,`type`)
);
插入一些数据:
INSERT INTO test VALUES(1, 10, 1);
INSERT INTO test VALUES(2, 20, 3);
INSERT INTO test VALUES(2, 10, 3);
INSERT INTO test VALUES(2, 30, 3);
查询数据:
mysql> SELECT SUM(count) as count FROM test WHERE id = 2;
+-------+
| count |
+-------+
| 9 |
+-------+
mysql> SELECT SUM(count) as count FROM test WHERE type = 10;
+-------+
| count |
+-------+
| 4 |
+-------+
效果很好,快速而灵活。
现在,我想重映射类型10到20型
UPDATE test SET type = 20 WHERE type = 10;
Duplicate entry '2-20' for key 'PRIMARY'
此处使用ON DUPLICATE KEY UPDATE
无效。
我认为应该可以使用创意插页,但我不确定。任何人都可以想到一种方法吗?
答案 0 :(得分:1)
更新查询时,您要创建包含id = 2
和type = 20
的多行,由于您的primary key
限制,这是不允许的。
您应该使用单个列作为主键,并在插入新行时使其自动增加。这样就保证了它的独特性。
答案 1 :(得分:1)
一种方法是放松"放松" PRIMARY KEY,意思是,将它从PRIMARY(唯一)KEY更改为非唯一KEY。这将允许重复值,并允许您的UPDATE语句成功,这样您将有两个(或更多)具有匹配(id,type)的行。 (请注意,这会使更新单行成为问题,因此您可能希望添加一个唯一的新列.AUTO_INCREMENT列可以很好地用于此。)
如果你不想这样做,那么另一种方法就是"结合"将类型10和类型20行的计数(对于每个id)计入类型20行,将类型10行的计数设置为零,并(可选)在单独的语句中删除冗余类型10行。
以下声明"结合"类型10和类型20按"映射"第一个选择中的10值为20。
-- combine count for types 10 and 20 as new count for type 20
-- and set count to zero for type 10
INSERT INTO test (id, `type`, `count`)
SELECT t.id
, IF(t.`type`=10,20,t.`type`) AS new_type
, SUM(t.`count`) AS `count`
FROM test t
WHERE t.`type` IN (10,20)
GROUP BY id, new_type
UNION ALL
SELECT u.id
, u.`type`
, 0 AS `count`
FROM test u
WHERE u.`type` = 10
ON DUPLICATE KEY UPDATE `count` = VALUES(`count`);
-- remove unnecessary type 10 rows.
DELETE FROM test WHERE `type` = 10 AND `count` = 0;
注意:第一个SELECT中的IF()表达式等同于:
CASE WHEN t.type = 10 THEN 20 ELSE t.type END
第二个选择是为我们提供所有需要更新的10行。我们使用UNION ALL运算符连接这两个结果集。
然后我们采用组合(连接)结果集,并将它们运行到插入中。我们遇到的任何地方都是重复的#34; key,我们通过ON DUPLICATE KEY子句执行更新操作。
您可能希望在事务中执行此操作(如果您使用的是InnoDB)并在执行DELETE
之前验证第一个语句是否成功完成。如果第一个语句抛出异常(可能有一个不稳定的触发器),那么你会想要ROLLBACK事务。如果由于某种原因DELETE失败,您也想要ROLLBACK(可能存在违反的外键约束。)
或者,您不一定需要执行DELETE,您可以保留10行,计数为零。
重要:
请勿同时实施这些解决方案!只有其中一个。
第一种方法是架构更改,它不需要任何数据更改。这一改变将使您的UPDATE成功。
第二种方法要求模式保持不变,并且取决于(id,type)上UNIQUE KEY的存在(和强制执行)。
答案 2 :(得分:0)
您已在两列上设置主键,更新后第三行主键与第二行相同,因此不允许使用。
最后你会有1..20; 2..20,2..20等。