Mysql 有没有办法优化此更新查询?

Mysql 有没有办法优化此更新查询?,mysql,sql,sql-update,mysql-error-1111,Mysql,Sql,Sql Update,Mysql Error 1111,我有一个名为“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), c

我有一个名为“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;
但这不起作用

更新:这是解决方案,感谢everbody:

您可以这样做:

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 function Invalid use of group function”,或者如果使用“group by c.master\U id”,则会得到“sql语法中有错误”

解决方案是将联接与子查询一起使用:

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;
但是由于这会从childtable中提取每一行,因此开销可能会比在原始sql中使用更多的子查询要大。因此,您应该向联接表中添加WHERE子句,以仅获取所需的行

另一个有趣的方法是这种语法,它与JOIN with WHERE子句的作用相同,但只有当您想用相同的值更新所有行并且子查询只返回一行时,才应该使用这种语法,因为子查询的结果会附加到结果中,并且可以像任何列一样使用

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中是否允许这样做,但SQLServer允许您在更新中使用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

我不知道MySQL中是否允许这样做,但SQLServer允许您在更新中使用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

您可以将数据选择到临时表中,然后使用该数据进行更新

如果您还希望在同一往返中插入“新”数据,请查看“插入到…”选择“从…”重复密钥更新时

若您已经在执行INSERT(若行不存在),那个么在本例中这将是多余的

例如:

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
注意!这是未经测试的代码,但我认为应该可以在更新中反向引用select结果


语法参考:

您可以将数据选择到临时表中,然后使用该数据进行更新

如果您还希望在同一往返中插入“新”数据,请查看“插入到…”选择“从…”重复密钥更新时

若您已经在执行INSERT(若行不存在),那个么在本例中这将是多余的

例如:

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
注意!这是未经测试的代码,但我认为应该可以在更新中反向引用select结果


语法参考:

将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;

将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;

您是否尝试过在更新之前进行计数并将其存储在变量中以传递到更新中?您有哪一个错误?您的更新是正确的。看起来您有几个答案可以在下面解决,但只想指出,这似乎是重复列和重复数据之间的一个非常非规范化的设计。您有吗您尝试在更新之前进行计数,并将其存储在变量中以传递到更新中?您有哪一个错误?您的更新是正确的。看起来您有两个答案可以在下面使用,但只想指出,这似乎是重复列和重复数据之间的一个非常非规范化的设计。如果您从我的答案中复制/粘贴MySQL的正确语法,我将删除该语法。@Wrikken,如果你确定这对MySQL不起作用,那么无论如何,OP应该接受你的答案。好吧,让我们说这是一个共同的努力(一开始我在尝试直接加入&一个群组,当然不起作用,我在想什么…)+1因为这是第一个。但是Wrikken是对的。对于MySQL,集合…部分必须在连接之后。如果你从我的答案中复制/粘贴MySQL的正确语法,我将删除该语法。@Wrikken,如果你确定这对MySQL不起作用,那么OP应该接受你的答案。那么,让我们说这是一个共同的努力(一开始我在尝试直接加入时出错&一个群组,当然不起作用,我当时是怎么想的…+1,因为这是第一个。但是Wrikken是对的。对于MySQL来说,集合…部分是在加入之后。很有魅力,但是(看看我问题中的更新)别忘了在子查询中添加where子句,否则您将从DB中拖出数百万行来连接一条记录;)工作起来很有魅力,但(看看我问题中的更新)别忘了在子查询中添加where子句,否则您将从DB中拖出数百万行来连接一条记录;)