MySQL中sum函数解读

2021-02-23 10:07:20 浏览数 (1)

文章简介

今天分享一下MySQL中的sum函数使用。该函数已经成为大家操作MySQL数据库中时常用到的一个函数,这个函数统计满足条件行中指定列的和,想必肯定大家都知道了,本身就没什么讲头了,这篇文章主要是通过几个小案例深入了解一下该函数,以及在做MySQL查询时如何使用sum函数做优化。

语法分析

SUM(DISTINCT expr) over_clause

  1. Returns the sum of expr. If the return set has no rows, SUM() returns NULL. The DISTINCT keyword can be used to sum only the distinct values of expr.
  2. If there are no matching rows, SUM() returns NULL.
  3. This function executes as a window function if over_clause is present.

上面几句是MySQL官方文档的一个功能描述。这里翻译一下大致的意思是什么。

  1. 返回expr表达式的和。如果没有返回行数,则返回NULL。这里的DISTINCT是为了去掉表达式expr中的重复值。
  2. 如果没有匹配到行,该函数也返回NULL。
  3. 如果设置了over_clause,则该函数作为窗口函数执行。对窗口函数不熟悉的,可以去了解一下MySQL中的窗口函数。

函数解释

在使用该函数时,我们应该思考一下,该函数是如何统计表达式中的和呢?可能有的程序员会想,这个函数直接去统计满足条件中所有行的总和。这么理解其实也没错,只是表达的不是很准确或者他不够真实了解运行原理。

实际上该函数是根据匹配行的值,一个一个累加起来的。这里举个例子,在一个订单表中满足条件的有10行数据,我们需要统计订单中的总价,sum的初始值是0,在匹配到第一行时,订单价格是10,此时sum就变成10,匹配到第二行,订单价格是20,这时候sum就是30。第三行订单价格是50,这时候sum就是80。按照这种方式依次累加。

行数

订单价格

sum值

第一行

10.00

10.00

第二行

20.00

30.00

第三行

30.00

60.00

第四行

40.00

100.00

第五行

50.00

150.00

第...行

...

...

第十行

100.00

550.00

实例演示

假设有下面一张表(Delivery),表结构如下:

代码语言:txt复制
 ----------------------------- --------- 
| Column Name                 | Type    |
 ----------------------------- --------- 
| delivery_id                 | int     |
| customer_id                 | int     |
| order_date                  | date    |
| customer_pref_delivery_date | date    |
| order_money                 | decimal |
 ----------------------------- --------- 

delivery_id 是表的主键。

该表保存着顾客的食物配送信息,顾客在某个日期下了订单,并指定了一个期望的配送日期(和下单日期相同或者在那之后)。如果顾客期望的配送日期和下单日期相同,则该订单称为 「即时订单」,否则称为「计划订单」。

里面有如下数据:

代码语言:txt复制
 ------------- ------------- ------------ ----------------------------- ------------- 
| delivery_id | customer_id | order_date | customer_pref_delivery_date | order_money |
 ------------- ------------- ------------ ----------------------------- ------------- 
| 1           | 1           | 2019-08-01 | 2019-08-02                  | 1.23        |
| 2           | 5           | 2019-08-02 | 2019-08-02                  | 1.01        |
| 3           | 1           | 2019-08-11 | 2019-08-11                  | 1.09        |
| 4           | 3           | 2019-08-24 | 2019-08-26                  | 1.00        |
| 5           | 4           | 2019-08-21 | 2019-08-22                  | 10.00       |
| 6           | 2           | 2019-08-11 | 2019-08-13                  | 12.09       |
 ------------- ------------- ------------ ----------------------------- ------------- 
实例一

统计出该表中所有的订单总金额。这里就很简单了,也是我们常用的使用方式,直接sum()参数填写某一个列就行了。按照上面的语法规则应该是一个表达式,实际上一列也是一个表达式。

代码语言:txt复制
select sum(order_money) from Delivery;
实例二

写一条 SQL 查询语句获取即时订单所占的百分比, 保留两位小数。这个可能就有一点点难度了,因为你很少用这个语法,如果你用过,就会发现也很简单。

首先你要理解,既然是查询某一个类型的占比,肯定就需要统计总和。我们可以分别去统计到订单总和$sum1,然后再去统计即时订单总和$sum2。然后在相除就可以了。但是这里明确要求一条SQL语句。那该如何解决呢?

这里就需要你深入了解一下sum的运行原理,我们可以设想我们一行一行的去读取数据,然后让sum一行一行的累计起来,是不是就可以得到$sum2的综合了?至于$sum1肯定很好统计,直接是表中行数的综合。

题解方式一:

代码语言:txt复制
select round (
    sum(case when order_date = customer_pref_delivery_date then 1 else 0 end) /
    count(*) * 100,
    2
) as immediate_percentage
from Delivery

题解方式二:

代码语言:txt复制
select round (
    sum(order_date = customer_pref_delivery_date) /
    count(*) * 100,
    2
) as immediate_percentage
from Delivery

这里当sum表达式满足条件,返回1,每次读到满足的一行数据,sum都加1,最后数据读完sum也就加完了。因此满足条件的总条数就出来了。

题目来源

改题目来源于LeetCode。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/immediate-food-delivery-i

还有一个比较不错的例子,推荐好好解读一下。加深该函数的使用场景。

https://www.jianshu.com/p/c19c99a60bb7

0 人点赞