簡體   English   中英

有沒有一種方法可以優化此更新查詢?

[英]Is there a way to optimize this update query?

我有一個名為“ 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相同,但是僅當您要更新具有相同值的所有行並且您的子查詢僅返回一行時,才應使用該語法,因為子查詢的結果得到附加到結果中,可以像任何列一樣使用。

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;

重寫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是否允許使用它,但是SQL Server允許您在更新中使用選擇的結果。

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 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中反向引用選擇結果。

語法參考: http : //dev.mysql.com/doc/refman/5.0/en/insert.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM