聚合函数
聚合函数作用于一组数据,并对一组数据返回一个值。
常见的聚合函数:SUM()
、MAX()
、MIN()
、AVG()
、COUNT()
对COUNT()聚合函数的更深一层理解
COUNT
函数的作用:计算指定字段在查询结果中出现的个数(不包含NULL值)
如果计算表中有多少条记录,如何实现?
方式1:COUNT(*)
方式2:COUNT(1)
方式3:COUNT(具体字段)
:不一定对!
为什么说使用方式3,得到的结果不一定正确呢?这是因为 COUNT
计算字段出现的个数时,是不计算NULL值的。或者说,COUNT(*)
会统计值为 NULL 的行,而 COUNT(字段)
不会统计此字段为 NULL 值的行
举个栗子,需求:查询公司中平均奖金率
SELECT SUM(commission_pct)/COUNT(commission_pct)
FROM employees;
上面的 mysql 代码 是错误的,因为 并不是所有的员工都有奖金率,可能存在没有奖金的员工,他/她的commission_pct
字段的记录为 NULL
。
正确的mysql语句如下:
SELECT SUM(commission_pct) / COUNT(IFNULL(commission_pct,0)), AVG(IFNULL(commission_pct,0))
FROM employees;
如何需要统计表中的记录数,使用COUNT(*)、COUNT(1)、COUNT(具体字段) 哪个效率更高呢?
如果使用的是 MyISAM
存储引擎,则三者效率相同,都是O(1)
如果使用的是 InnoDB
存储引擎,则三者效率:COUNT(*) = COUNT(1) > COUNT(字段)
GROUP BY 的一些鲜为人知的事儿
SELECT
中出现的非组函数的字段必须声明在 ORDER BY
中。反而,在 ORDER BY
中声明的字段可以不出现在SEELCT
中。
SELECT job_id,department_id,AVG(salary)
FROM employees
GROUP BY job_id,department_id;
GROUP BY
声明在FROM
后面,WHERE
后面,ORDER BY
前面,LIMIT
前面。
当使用ROLLUP时,不能同时使用ORDER BY子句进行结果排序,即ROLLUP和ORDER BY是互相排斥的。
HAVING 的小秘密
- 如果过滤条件中使用了聚合函数,则必须使用
HAVING
来替换WHERE
,否则报错。 HAVING
必须声明在GROUP BY
的后面。- 在开发中,我们使用
HAVING
的前提是SQL
中使用了GROUP BY
SELECT department_id,MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary) > 10000;
当过滤条件中没有聚合函数时,则此过滤条件声明在WHERE中或HAVING中都可以,但是建议大家声明在WHERE中。
WHERE
与 HAVING
的对比
- 从适用范围上来讲,
HAVING
的适用范围更广。 - 如果过滤条件中没有聚合函数:这种情况下,
WHERE
的执行效率要高于HAVING
SELECT查询的结构
方式1:
SELECT ...,....,...
FROM ...,...,....
WHERE 多表的连接条件
AND 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
方式2:
SELECT ...,....,...
FROM ... JOIN ...
ON 多表的连接条件
JOIN ...
ON ...
WHERE 不包含组函数的过滤条件
AND/OR 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
其中:
(1)from:从哪些表中筛选
(2)on:关联多表查询时,去除笛卡尔积
(3)where:从表中筛选的条件
(4)group by:分组依据
(5)having:在统计结果中再次筛选
(6)order by:排序
(7)limit:分页
SELECT语句执行顺序
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT 的字段 -> DISTINCT -> ORDER BY -> LIMIT