Appearance
聚合(聚集、分组)函数
对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。
AVG() / SUM()
只适用于数值类型的字段或变量 AVG,SUM 遇到 NULL 时不会计算
sqlSELECT AVG(salary), SUM(salary) FROM employees; # 0,对字符串求总值无意义。 SELECT SUM(last_name) FROM employees;MAX() / MIN()
适用于数值类型、字符串类型、日期时间类型的字段或变量
sqlSELECT MAX(salary), MIN(salary) FROM employees; # Zlotkey Abel # 字符串比较大小有意义 SELECT MAX(last_name), MIN(last_name) FROM employees;COUNT()
计算指定字段在查询结果中出现的个数
sql# 107 107 107 107 107 107 107 SELECT COUNT(employee_id), COUNT(salary), COUNT(2 * salary), COUNT(1), COUNT(2), COUNT(*) FROM employees; # 106,不包括 NULL。 # 因此可以推断出 AVG = SUN / COUNT SELECT COUNT(department_id) FROM employees; # 计算表中有多少条记录 SELECT COUNT(*) FROM employees; SELECT COUNT(1) FROM employees; # 要保证该字段不为 NULL SELECT COUNT(具体字段) FROM employees; # 计算平均奖金率 SELECT SUM(commission_pct) / COUNT(IFNULL(commission_pct, 0)) # 或 # SELECT SUM(commission_pct) / COUNT(*) FROM employees; # 或 AVG(IFNULL(commission_pct, 0))GROUP BY
sql# 查询各个部门的平均工资。 SELECT department_id, AVG(salary) FROM employees GROUP BY department_id; # 查询各个 jon_id 的平均工资 SELECT job_id, AVG(salary) FROM employees GROUP BY job_id; # 查询各个 department_id 下各个 jon_id 的平均工资 SELECT department_id, job_id, AVG(salary) FROM employees GROUP BY department_id, job_id; # 或者这样写,结果是一样的。 # GROUP BY job_id, department_id; # 错误写法,但是 8.0 不报错。 # SELECT 中除聚合函数使用的字段外,其它字段一定要出现在 GROUP BY 中 # 但 GROUP BY 中出现的字段不一定要出现在 SELECT 中。 SELECT department_id, job_id, AVG(salary) FROM employees GROUP BY department_id; # GROUP BY 声明在 FROM 后面、WHERE 后面、ORDER BY 前面、LIMIT 前面。 # WITH ROLLUP 会在结果最后增加一条记录,该记录会对 GROUP BY 后的所有分组 # 再执行一次 ??? # 当使用 WITH ROLLUP 时,不能使用 ORDER BY 进行排序,因为会将新增的这条记录也进行 # 排序。 SELECT department_id, AVG(salary), SUM(salary) FROM employees GROUP BY department_id WITH ROLLUP;HAVING
用来过滤数据,往往配合 GROUP BY 使用。
sql# 查询各个部门最高工资比 10000 高的部分信息 SELECT department_id, MAX(salary) FROM employees # 报错 # 如果过滤条件中使用了聚合函数,必须使用 HAVING 替换 WHERE WHERE MAX(salary) > 10000 GROUP BY department_id SELECT department_id, MAX(salary) FROM employees # 报错 HAVING 必须在 GROUP BY 后面 HAVING MAX(salary) > 10000; GROUP BY department_id SELECT department_id, MAX(salary) FROM employees GROUP BY department_id HAVING MAX(salary) > 10000; # 查询部门 id 为 10, 20, 30, 40 这 4 个部门中最高工资比 10000 高的部门信息 # 方式 1,执行效率高于方式 2,推荐。 SELECT department_id, MAX(salary) FROM employees WHERE department_id IN (10, 20, 30, 40) GROUP BY department_id HAVING MAX(salary) > 10000; # 方式 2 SELECT department_id, MAX(salary) FROM employees GROUP BY department_id HAVING MAX(salary) > 10000 AND department_id IN (10, 20, 30, 40); # 当过滤条件中有聚合函数时,则此过滤条件必须声明在 HAVING 中 # 当过滤条件中没有聚合函数时,则此过滤条件必须声明在 WHERE 中或 HAVING 中都可以, # 但是建议声明在 WHERE。
WHERE vs HAVING
区别1:WHERE 可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件; HAVING 必须要与 GROUP BY 配合使用,可以把分组计算的函数和分组字段作为筛选条件。 这决定了,在需要对数据进行分组统计的时候,HAVING 可以完成 WHERE 不能完成的任务。这是因为, 在查询语法结构中,WHERE 在 GROUP BY 之前,所以无法对分组结果进行筛选。HAVING 在 GROUP BY 之 后,可以使用分组字段和分组中的计算函数,对分组的结果集进行筛选,这个功能是 WHERE 无法完成 的。另外,WHERE排除的记录不再包括在分组中。 区别2:如果需要通过连接从关联表中获取需要的数据,WHERE 是先筛选后连接,而 HAVING 是先连接 后筛选。 这一点,就决定了在关联查询中,WHERE 比 HAVING 更高效。因为 WHERE 可以先筛选,用一 个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也比较高。HAVING 则需要 先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用 的资源就比较多,执行效率也较低。 小结如下: WHERE 先筛选数据再关联,执行效率高 不能使用分组中的计算函数进行筛选 HAVING 可以使用分组中的计算函数 在最后的结果集中进行筛选,执行效率较低
开发中的选择: WHERE 和 HAVING 也不是互相排斥的,我们可以在一个查询里面同时使用 WHERE 和 HAVING。包含分组 统计函数的条件用 HAVING,普通条件用 WHERE。这样,我们就既利用了 WHERE 条件的高效快速,又发 挥了 HAVING 可以使用包含分组统计函数的查询条件的优点。当数据量特别大的时候,运行效率会有很 大的差别。