• MySQL---聚合函数


    聚合函数介绍

    聚合(或聚集、分组)函数,它是对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。
    
    
    • 1
    • 2

    AVG和SUM函数

    AVG / SUM :只适用于数值类型的字段(或变量)
    
    SELECT AVG(salary),SUM(salary),AVG(salary) * 107
    FROM employees;
    如下的操作没有意义
    SELECT SUM(last_name),AVG(last_name),SUM(hire_date)
    FROM employees;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    MIN和MAX函数

    MAX / MIN :适用于数值类型、字符串类型、日期时间类型的字段(或变量)
    
    SELECT MAX(salary),MIN(salary)
    FROM employees;
    
    SELECT MAX(last_name),MIN(last_name),MAX(hire_date),MIN(hire_date)
    FROM employees;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    COUNT函数

    作用:计算指定字段在查询结构中出现的个数(不包含NULL值的)
    
    SELECT COUNT(employee_id),COUNT(salary),COUNT(2 * salary),COUNT(1),COUNT(2),COUNT(*)
    FROM employees ;
    
    • 1
    • 2
    • 3
    • 4
    如果计算表中有多少条记录,如何实现?
    方式1COUNT(*)
    方式2COUNT(1)
    方式3COUNT(具体字段) : 不一定对!
    COUNT(expr) 返回expr不为空的记录总数。
    
     如何需要统计表中的记录数,使用COUNT(*)COUNT(1)COUNT(具体字段) 哪个效率更高呢?
     如果使用的是MyISAM 存储引擎,则三者效率相同,都是O(1)
     如果使用的是InnoDB 存储引擎,则三者效率:COUNT(*) = COUNT(1)> COUNT(字段)
    
    问题:用count(*)count(1)count(列名)谁好呢?
    其实,对于MyISAM引擎的表是没有区别的。这种引擎内部有一计数器在维护着行数。
    Innodb引擎的表用count(*),count(1)直接读行数,复杂度是O(n),因为innodb真的要去数一遍。但好
    于具体的count(列名)。
    
    问题:能不能使用count(列名)替换count(*)?
    不要使用 count(列名)来替代 count(*)count(*) 是 SQL92 定义的标准统计行数的语法,跟数
    据库无关,跟 NULL 和非 NULL 无关。
    说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    group by

    基本使用

    查询各个部门的平均工资,最高工资
    
    SELECT department_id,AVG(salary),SUM(salary)
    FROM employees
    GROUP BY department_id
    
    • 1
    • 2
    • 3
    • 4
    • 5
    查询各个job_id的平均工资
    SELECT job_id,AVG(salary)
    FROM employees
    GROUP BY job_id;
    
    • 1
    • 2
    • 3
    • 4

    使用多个列分组

    查询各个department_id,job_id的平均工资
    方式1SELECT department_id,job_id,AVG(salary)
    FROM employees
    GROUP BY  department_id,job_id;
    方式2SELECT job_id,department_id,AVG(salary)
    FROM employees
    GROUP BY job_id,department_id;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    GROUP BY中使用WITH ROLLUP

    使用 WITH ROLLUP 关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所
    有记录的总和,即统计记录数量
    
    SELECT department_id,AVG(salary)
    FROM employees
    GROUP BY department_id WITH ROLLUP;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    查询各个部门的平均工资,按照平均工资升序排列
    
    SELECT department_id,AVG(salary) avg_sal
    FROM employees
    GROUP BY department_id
    ORDER BY avg_sal ASC;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    当使用ROLLUP时,不能同时使用ORDER BY子句进行结果排序,即ROLLUP和ORDER BY是互相排斥的。
    错误的:
    SELECT department_id,AVG(salary) avg_sal
    FROM employees
    GROUP BY department_id WITH ROLLUP
    ORDER BY avg_sal ASC;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    小结

    结论1SELECT中出现的非组函数的字段必须声明在GROUP BY 中。
          反之,GROUP BY中声明的字段可以不出现在SELECT中。
    
    结论2GROUP BY 声明在FROM后面、WHERE后面,ORDER BY 前面、LIMIT前面
    
    • 1
    • 2
    • 3
    • 4

    HAVING(作用:用来过滤数据的)

    要求1:如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE。否则,报错。
    要求2HAVING 必须声明在 GROUP BY 的后面。
    要求3:开发中,我们使用HAVING的前提是SQL中使用了GROUP BY
    
    #正确的写法:
    SELECT department_id,MAX(salary)
    FROM employees
    GROUP BY department_id
    HAVING MAX(salary) > 10000;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    查询部门id为10,20,30,404个部门中最高工资比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;
    
    方式2SELECT 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中。
    
    WHEREHAVING 的对比
    1. 从适用范围上来讲,HAVING的适用范围更广。 
    2. 如果过滤条件中没有聚合函数:这种情况下,WHERE的执行效率要高于HAVING
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    SELECT的执行过程

    SELECT 语句的完整结构
    
    sql92语法:
    SELECT ....,....,....(存在聚合函数)
    FROM ...,....,....
    WHERE 多表的连接条件 AND 不包含聚合函数的过滤条件
    GROUP BY ...,....
    HAVING 包含聚合函数的过滤条件
    ORDER BY ....,...(ASC / DESC )
    LIMIT ...,....
    
    sql99语法:
    SELECT ....,....,....(存在聚合函数)
    FROM ... (LEFT / RIGHT)JOIN ....ON 多表的连接条件 
    (LEFT / RIGHT)JOIN ... ON ....
    WHERE 不包含聚合函数的过滤条件
    GROUP BY ...,....
    HAVING 包含聚合函数的过滤条件
    ORDER BY ....,...(ASC / DESC )
    LIMIT ...,....
    
    SQL语句的执行过程:
    FROM ...,...-> ON -> (LEFT/RIGNT  JOIN) -> WHERE -> GROUP BY -> HAVING -> SELECT -> 
    DISTINCT ->  ORDER BY -> LIMIT
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    聚合函数练习

    1.where子句可否使用组函数进行过滤?

    NO
    
    • 1

    2.查询公司员工工资的最大值,最小值,平均值,总和

    SELECT MAX(salary), MIN(salary), AVG(salary), SUM(salary)
    FROM employees;
    
    • 1
    • 2

    3.查询各job_id的员工工资的最大值,最小值,平均值,总和

    SELECT job_id, MAX(salary), MIN(salary), AVG(salary), SUM(salary)
    FROM employees
    GROUP BY job_id;
    
    • 1
    • 2
    • 3

    4.选择具有各个job_id的员工人数

    SELECT job_id, COUNT(*)
    FROM employees
    GROUP BY job_id;
    
    • 1
    • 2
    • 3

    5. 查询员工最高工资和最低工资的差距(DIFFERENCE)

    SELECT MAX(salary), MIN(salary), MAX(salary) - MIN(salary) DIFFERENCE
    FROM employees;
    
    • 1
    • 2

    6.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内

    SELECT manager_id, MIN(salary)
    FROM employees
    WHERE manager_id IS NOT NULL
    GROUP BY manager_id
    HAVING MIN(salary) > 6000;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    7.查询所有部门的名字,location_id,员工数量和平均工资,并按平均工资降序

    SELECT department_name, location_id, COUNT(employee_id), AVG(salary) avg_sal
    FROM employees e RIGHT JOIN departments d
    ON e.`department_id` = d.`department_id`
    GROUP BY department_name, location_id
    ORDER BY avg_sal DESC;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8.查询每个工种、每个部门的部门名、工种名和最低工资

    SELECT department_name,job_id,MIN(salary)
    FROM departments d LEFT JOIN employees e
    ON e.`department_id` = d.`department_id`
    GROUP BY department_name,job_id
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    Kylin 使用心得
    Java项目:ssm学生综合素质评价系统
    PlantUML Integration 编写短信服务类图
    Sql力扣算法:185. 部门工资前三高的所有员工
    Vue精美简洁登录页
    C++基础入门(超详细)
    【科学文献计量】ChatGPT的api使用及实现上下文处理
    带头双向循环链表的实现
    昆仑万维旗下StarMaker VR成功加入Oculus开发者计划 获Oculus资金支持
    Mybatis数据库驱动
  • 原文地址:https://blog.csdn.net/qq_53022114/article/details/126061419