2010-06-17 160 views
0

我有一個名爲「父母」的主表和一個名爲「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‘

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

的解決方案「,如果您使用您的SQL語法錯誤’是使用一個子查詢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; 

但由於這從childtable拉每一行的開銷可能比使用更多的子查詢像原來的SQL更大,所以你應該在WHERE子句添加到連接的。表只能得到你需要的行

另一個有趣的方法就是這種語法,它與JOIN和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; 
+0

你嘗試過更新之前做你的計數,並將其存儲伊娜變量傳遞到您的更新? – 2010-06-17 11:22:39

+0

你有哪個錯誤?您的更新是正確的。 – ksogor 2010-06-17 11:31:25

+0

它看起來像你有幾個應該在下面工作的答案,但只是想指出,這似乎是重複的列和重複的數據之間非常規範化的設計。 – 2010-06-17 13:55:50

回答

2

重寫利芬的解決方案到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; 
+0

工程就像一個魅力,但(看看我的問題的更新)不要忘記添加一個where子句的子查詢,或者你會從數據庫拉數百萬行只是爲了加入一個記錄;) – 2010-06-21 11:13:36

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 
+0

+1,這正是我如何做 – 2010-06-17 11:58:31

+0

如果您從我的答案中複製/粘貼MySQL的正確語法,我會刪除那一個。 – Wrikken 2010-06-17 12:03:36

+0

@Wrikken,如果您確定這不適用於MySQL,那麼無論如何,OP應該接受您的答案。 – 2010-06-17 12:13:04

0

您可以將數據選擇到臨時表中,然後使用該數據進行更新。

如果你也想在同一個往返插入「新」的數據,看看INSERT INTO ... SELECT FROM ...對重複密鑰更新...

如果你已經在做,如果插入的行不存在,那麼這個例子就是多餘的。

例如:

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

相關問題