mysql SUM 函数使用问题和精度计算
先看一下函数语法:
SUM(DISTINCT expression)
- 如果在没有返回匹配行 SELECT 语句中使用 SUM 函数,则 SUM 函数返回 NULL,而不是0。
- DISTINCT 运算符允许计算集合中的不同值。
- SUM 函数忽略计算中的 NULL 值。
在没有匹配行 SUM 会返回 NULL 而不是 0,这是我之前没有注意到的点。
为了让结果不会 NULL 而是 0,可以使用 COALESCE(SUM(money), 0)
或者 IFNULL(SUM(money), 0)
。
如果需要设置保留小数精度,可以使用 FORMAT(COALESCE(SUM(money), 0), 2)
。
除 sql 处理精度以外,也可以通过 php 函数处理精度计算:php 高精度计算问题
一般用法
示例:查询完成订单总收益(这里 status=3 表示完成)
select SUM(money) total from orders where status = 3;
与 group by 联合
SUM 属于聚合函数,可以与 group by 进行分组查询
示例:查询店铺订单总收益
select SUM(money) total from orders where status = 3 group by shop_id;
注意: where 子句需要放在 group by 的前面。
与 having 联合
如果需要对于 SUM 结果进行筛选,此时需要用到 having。
示例:查询店铺订单总收益 > 0
select SUM(money) total from orders where status = 3 group by shop_id having total > 0;
增加对 SUM 结果的排序和分页
SELECT SUM(money) total FROM orders
WHERE status = 3
GROUP BY shop_id
HAVING total > 0
ORDER BY total DESC
LIMIT 0,10
SUM 与 limit 单独联动时,limit 约束返回行数是不可行的,最终只会返回一行。
如果需要对表记录约束去除行数,可以考虑使用子查询。
示例:前十订单金额的店铺总金额
SELECT shop_id, SUM(money) total FROM (
SELECT shop_id, money FROM orders
WHERE status = 3
ORDER BY money DESC
LIMIT 0, 10) rank
GROUP BY shop_id
HAVING total > 0
ORDER BY total DESC
LIMIT 0,10
另外发现:FORMAT 函数可以在 having 中使用,而在 order by 子句中是不可行的,不会报错,但也不会按照 FORMAT 后的结果排序。即 order by FORMAT(COALESCE(SUM(money), 0), 2) DESC
是不会按照店铺订单总金额倒序排序的。
与 join 联合
示例:完结订单总收益
SELECT SUM(profits.money) total FROM orders
LEFT JOIN profits ON orders.id = profits.order_id
WHERE orders.status = 3
GROUP BY orders.shop_id
HAVING total > 0
ORDER BY total DESC
LIMIT 0,10
注意:需要确保联查记录 1:1,如果出现 1:n 的情况,可能会造成数据重复统计的错误。