【发布时间】:2011-03-04 22:04:48
【问题描述】:
我有一个名为“parent”的主表和一个名为“childs”的相关表
现在我对主表运行查询,以使用来自子表的总和来更新一些值,如下所示。
UPDATE master m SET
quantity1 = (SELECT SUM(quantity1) FROM childs c WHERE c.master_id = m.id),
quantity2 = (SELECT SUM(quantity2) FROM childs c WHERE c.master_id = m.id),
count = (SELECT COUNT(*) FROM childs c WHERE c.master_id = m.id)
WHERE master_id = 666;
这按预期工作,但不是一个好的风格,因为我基本上对同一个结果进行多个 SELECT 查询。有没有办法优化它? (首先进行查询并存储值不是一种选择。
我试过了:
UPDATE master m SET (quantity1, quantity2, count) = (
SELECT SUM(quantity1), SUM(quantity2), COUNT(*)
FROM childs c WHERE c.master_id = m.id
) WHERE master_id = 666;
但这不起作用。
更新:这是解决方案,感谢大家:
你可以这样做:
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = c.quantity1,
master.count = 1
如果您一次只有一个子记录。但是,如果您想在不工作的联接表中使用像 SUM() 这样的组函数。如果您离开“分组依据”部分,您会得到“组函数的无效使用”,或者如果您使用“GROUP BY c.master_id”,则会出现“您的 sql 语法有错误”
-- This doesnt work :(
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = SUM(c.quantity1),
master.count = COUNT(c.*)
GROUP by c.master_id
解决方案是使用带有子查询的 JOIN:
UPDATE master m
INNER JOIN
(
SELECT master_id,
SUM(quantity1) as quantity1,
COUNT(*) as count
FROM childs c
GROUP BY master_id
) c
ON c.master_id = m.master_id
SET m.quantity1 = c.quantity1,
m.count = c.count
WHERE m.master_id = 666;
但是由于这会从子表中提取每一行,因此开销可能会比使用更多子查询(如在原始 sql 中)更大。因此,您应该在连接表中添加 WHERE 子句,以仅获取您需要的行。
另一种有趣的方法是这种语法,它与使用 WHERE 子句的 JOIN 相同,但仅当您想要更新具有相同值的所有行并且您的子查询仅返回一行时才应使用,因为结果来自子查询被附加到结果中,可以像任何列一样使用。
UPDATE master m,
(
SELECT SUM(c.quantity1) as sum_of_quantity,
COUNT(*) as rowcount FROM child c WHERE c.master_id = 666
) as c
SET m.quantity1 = c.sum_of_quantity,
m.count = c.rowcount
WHERE m.master_id = 666;
【问题讨论】:
-
您是否尝试过在更新之前进行计数并将其存储在变量中以传递到您的更新中?
-
你有什么错误?您的更新是正确的。
-
看起来您有几个答案应该在下面起作用,但只是想指出这似乎是重复列和重复数据之间的非常非规范化的设计。
标签: mysql sql sql-update mysql-error-1111