2015-05-08 107 views
1

我需要更新多個選擇的總和計算的字段。選擇部分工作,但我不能找到一種方法來更新用戶表更新查詢SUM多個選擇

user 

+------+---------+ 
| id | total | 
+------+---------+ 
| 1 |   | 
| 2 |   | 

unita 

+------+-------+-----+ 
| id | uid | num | 
+------+-------+-----+ 
| 1 | 1  | 25 | 
| 1 | 2  | 10 | 

unitb 

+------+-------+-----+ 
| id | uid | num | 
+------+-------+-----+ 
| 9 | 1  | 225 | 
| 9 | 2  | 10 | 

class 

+------+--------+------+ 
| id | name | cost | 
+------+--------+------+ 
| 1 | class1 | 100 | 
| 9 | class9 | 500 | 

SELECT uid, SUM(score) FROM (
    SELECT unita.uid, SUM(class.cost * unita.num) AS cost FROM unita, class WHERE unita.id = class.id GROUP BY unita.uid 
    UNION 
    SELECT unita.uid, SUM(class.cost * unitb.num) AS cost FROM unitb, class WHERE unitb.id = class.id GROUP BY unitb.uid 
) x GROUP BY uid 

update命令應總結每個用戶

User 1: (25*100)+(225*500) = 115000 
User 2: (10*100)+(10*500) = 6000 

它這個可能一切代價1個SQL命令中。該單元表被鎖定,所以我不能做任何修改

+1

只需添加'更新用戶u連接(您的選擇查詢,直到通過uid組)「y上的y.uid = u.uid set u.total = y.score'也給選擇部分的別名作爲'SELECT uid ,SUM(評分)作爲得分...' –

+0

http://stackoverflow.com/questions/8057565/mysql-update-statement-inner-join-tables –

+0

參見下面[鏈接]此鏈接[1] 希望它能幫助你。 [1]:http://stackoverflow.com/questions/1262786/mysql-update-query-based-on-select-query –

回答

1

您可以使用join的結果,從你的子查詢帶來:

UPDATE user u JOIN 
     (SELECT uid, SUM(score) as total 
     FROM (SELECT unita.uid, SUM(class.cost * unita.num) AS cost 
       FROM unita JOIN 
        class 
        ON unita.id = class.id 
       GROUP BY unita.uid 
       UNION ALL 
       SELECT unita.uid, SUM(class.cost * unitb.num) AS cost 
       FROM unitb JOIN 
        class 
        ON unitb.id = class.id 
       GROUP BY unitb.uid 
      ) x 
     GROUP BY uid 
     ) newvals 
     ON u.id = newvals.uid 
    SET u.total = newvals.total; 

三題:

  1. 注意使用UNION ALL代替UNION。這不僅可以提高性能,因爲不會消除重複項,但是如果兩個子查詢都返回相同的值,它也會修復潛在的問題。
  2. 請注意使用正確的join語法。簡單的規則:從不在from子句中使用逗號。
  3. 如果不匹配,則不會將總數設置爲0。如果您需要,請將join更改爲left join,將set更改爲SET u.total = COALESCE(newvals.total, 0)
+0

感謝您的幫助。我從來不知道這是可能的。 – EspieNL

0

您可以使用更新聯接語法:

UPDATE `user` u 
JOIN (SELECT uid, SUM(score) AS total 
     FROM  (SELECT unita.uid, SUM(class.cost * unita.num) AS cost 
        FROM  unita, class 
        WHERE unita.id = class.id 
        GROUP BY unita.uid 
        UNION ALL 
        SELECT unitb.uid, SUM(class.cost * unitb.num) AS cost 
        FROM  unitb, class 
        WHERE unitb.id = class.id 
        GROUP BY unitb.uid) x 
     GROUP BY uid) s ON s.uid = u.id 
SET u.total = s.total 

注:

  1. 在OP內查詢有一個錯誤。由於它使用union而不是union all,所以如果在兩個單元中相同的uid具有相同的總得分,則它將僅被計數一次,而不是兩次。上面的查詢修復了這個問題。
  2. 隱式連接已被棄用了很長時間。上述查詢仍然使用它們來計算OP的樣式,但強烈建議使用顯式連接。

如:

UPDATE `user` u 
JOIN (SELECT uid, SUM(score) AS total 
     FROM  (SELECT unita.uid, SUM(class.cost * unita.num) AS cost 
        FROM  unita 
        JOIN  class ON unita.id = class.id 
        GROUP BY unita.uid 
        UNION ALL 
        SELECT unitb.uid, SUM(class.cost * unitb.num) AS cost 
        FROM  unitb 
        JOIN  class ON unitb.id = class.id 
        GROUP BY unitb.uid) x 
     GROUP BY uid) s ON s.uid = u.id 
SET u.total = s.total 
+0

是所有這些小分組依據,不是一個很大的一個更有效? – Strawberry

+0

嗨Mureinik,謝謝你的幫助。我將戈登斯的答案標記爲解決方案。他的回答比較完整。 – EspieNL