简体   繁体   English

UPDATE查询SUM多项选择

[英]UPDATE query SUM multiple selects

I need to update a field calculated by the sum of multiple selects. 我需要更新通过多次选择的总和计算的字段。 The selection part is working, but I can't find a way to update the user table 选择部分正在工作,但我找不到更新用户表的方法

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

The update command should sum all cost per user 更新命令应汇总每位用户的所有费用

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

It this possible within 1 SQL command. 这可以在1条SQL命令中完成。 The unit tables are locked, so I can't modify anything 单位表已锁定,因此我无法进行任何修改

You can use join to bring in the results from your subquery: 您可以使用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;

Three notes: 三个注意事项:

  1. Note the use of UNION ALL instead of UNION . 注意使用UNION ALL代替UNION Not only does this improve performance because duplicates are not eliminated, but it also fixes a potential problem if both subqueries return the same value. 由于不消除重复项,因此不仅可以提高性能,而且还可以解决两个子查询返回相同值时的潜在问题。
  2. Note the use of proper join syntax. 注意使用正确的join语法。 Simple rule: never use commas in the from clause. 简单的规则:请勿在from子句中使用逗号。
  3. This will not set the total to 0 if there is no match. 如果没有匹配项,则不会将总数设置为0。 If you desire this, change the join to a left join and the set to SET u.total = COALESCE(newvals.total, 0) . 如果你想要这个,改变joinleft joinsetSET u.total = COALESCE(newvals.total, 0)

You can use the update-join syntax: 您可以使用update-join语法:

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

Notes: 笔记:

  1. The inner query in the OP has a bug. OP中的内部查询存在错误。 Since it uses union instead of union all , if the same uid has the same total score in both units, it will only be counted once, instead of twice. 由于它使用union而不是union all ,因此,如果相同的uid在两个单位中的总得分相同,则只会被计数一次,而不是两次。 The above query fixes this. 上面的查询解决了这个问题。
  2. Implicit joins have been deprecated for ages. 隐式连接已经过了很长一段时间了。 The above query still uses them to math the OP's style, but the use of explicit joins is highly recommended. 上面的查询仍然使用它们来数学OP的样式,但是强烈建议使用显式联接。

Eg: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM