我有一个名为“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”部分或“如果您使用”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相同,但是你应该只使用if if如果要更新具有相同值的所有行,并且子查询只返回一行,因为结果来自子查询被附加到结果中,可以像任何列一样使用。
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;
答案 0 :(得分:2)
重写Lieven的MySQL解决方案:
UPDATE master m
JOIN (
SELECT master_id
, SUM(quantity1) as quantity1
, SUM(quantity2) as quantity2
, COUNT(*) as count
FROM childs c
GROUP BY
master_id
) c
ON c.master_id = m.master_id
SET
m.quantity1 = c.quantity1
,m.quantity2 = c.quantity2
,m.count = c.count
WHERE m.master_id = 666;
答案 1 :(得分:1)
我不知道MySQL中是否允许它,但SQL Server允许您在更新中使用select的结果。
UPDATE master m SET
quantity1 = c.quantity1
, quantity2 = c.quantity2
, count = c.count
FROM master m
INNER JOIN (
SELECT master_id
, quantity1 = SUM(quantity1)
, quantity2 = SUM(quantity2)
, count = COUNT(*)
FROM childs c
WHERE master_id = 666
GROUP BY
master_id
) c ON c.master_id = m.master_id
答案 2 :(得分:0)
您可以将数据选择到临时表中,然后使用该数据进行更新。
如果您还想在同一个往返中插入“新”数据,请查看INSERT INTO ... SELECT FROM ... ON DUPLICATE KEY UPDATE ...
如果你已经在插入行中,如果行不存在,那么这个例子就是多余的。
示例:
INSERT INTO master m (id, quantity1, quantity2, count)
SELECT master_id, SUM(quantity1) q1, SUM(quantity2) q1, COUNT(*) c
FROM childs
GROUP BY master_id
ON DUPLICATE KEY UPDATE
m.quantity1 = q1,
m.quantity2 = q2,
m.count = c
请注意!这是未经测试的代码,但我认为应该可以在UPDATE中反向引用选择结果。