3.分组函数
功能:用作统计使用,又称为聚合函数或统计函数
分类:sum求和 , avg求平均值 , max最大值,min最小值,count计算个数
特点:
sum,avg可以处理数值类型 , max ,min ,count可以处理任何类型
以上分组函数忽略null值
可以和distinct(去重)搭配只用
使用count(*)统计行数
和分组函数一同查询的字段要求是group by后的字段
基本使用
-
count的详细介绍
count(1)是在没行的前面加了一列常量1,然后计算有多少行
-
-- 基本使用 SELECT SUM(salary) , MAX(salary) , MIN(salary) , COUNT(commission_pct) , AVG(salary) FROM employees; -- 以上都是忽略null值的,以count为例 , 表中有107条数据 -- 结果:35 SELECT COUNT(commission_pct) FROM employees; -- 可以支持distinct去重使用 -- 结果:11 有107条数据,去重过后剩余11条 SELECT COUNT(DISTINCT department_id) FROM employees; -- count的详解 -- count的参数如果是字段的话,会作用到这一整列 , 但是使用count(*)会计算所有的行数 -- 另外count(1)可以计算所有的行数 SELECT count(*) FROM employees; SELECT count(1) FROM employees; -- count里的参数可以常量 , 和是1的类似 , 但是性能不好
3.1.测试
相差天数使用的函数可以用DATEDIFF
, TIMEDIFF
相差时间 xx:xx:xx表示
-- 查询员工表中的最大入职时间和最小入职时间的相差天数
SELECT DATEDIFF(MAX(hiredate),MIN(hiredate)) AS day
FROM employees;
-- 查询部门编号为90的员工的个数
SELECT COUNT(*)
FROM employees
WHERE department_id = 90;
4.排序(order by)
-
语法:
select 查询列表
from 表
【where 筛选条件】
order by 排序列表 【ASC | DESC】
-
特点:
1.ASC 代表升序 , DESC代表降序。 不写默认是ASC
2.order by 子句单个字段,多个字段,表达式,别名,函数,表达式排序
3.order by 子句放在查询语句的最后面
4.子句中可以放分组函数
-
案例
-- 查询部门编号>=90,按照入职时间排序 【添加筛选条件】
SELECT * FROM employees WHERE department_id >= 90 ORDER BY hiredate DESC;
-- 按照年薪的高低显示员工的信息和 年薪【按照表达式排序】
SELECT first_name , job_id , salary , (IFNULL(salary,0))*12 AS 年薪 FROM employees ORDER BY (IFNULL(salary,0))*12;
-- 按照年薪的高低显示员工的信息和 年薪【按照别名排序】
-- 和上面的完全相同
SELECT first_name , job_id , salary , (IFNULL(salary,0))*12 AS 年薪 FROM employees ORDER BY 年薪;
-- 按照姓名的长度显示员工的姓名和工资 【按照函数排序】
SELECT LENGTH(IFNULL(first_name,'')) AS name_length , job_id , salary from employees ORDER BY name_length;
-- 查询员工的信息,要求先按照工资排序,再按照员工编号排序【按多个字段进行排序】
SELECT first_name , job_id , salary FROM employees ORDER BY salary DESC, job_id;
4.1.测试
-- 1. 查询员工的姓名和部门号和年薪,按年薪降序 按姓名升序
SELECT last_name , manager_id , (IFNULL(salary,0))*12 AS 年薪
FROM employees
ORDER BY 年薪 DESC , last_name;
-- 2. 选择工资不在8000-17000的员工的姓名和工资,按工资降序
SELECT last_name , salary
from employees where
-- salary NOT BETWEEN 7000 AND 17000
salary < 7000 OR salary >17000
ORDER BY salary DESC;
或者是
-- 3. 查询邮箱中包含E的员工的信息,并先按照邮箱的子节数降序 , 再按照部门号升序
SELECT *
FROM employees
WHERE email like '%E%'
ORDER BY LENGTH(email) DESC , department_id;
5.分组 (grounp by)
-
语法:
select column , grounp_function(column) 4
from table 1
[where condition] 2
[group by group_by_expression] 3
[order by column] 5
-
特点:
-
group by 后面跟的可以是字段,也可以是表达式
-
group by 后面和having后面都支持别名
-
可以按照多个字段进行分组
-
执行顺序应该是上面标注的
处理分组的问题:
-
要知道
分组
是以某个字段
进行分组的 ,那么影响到的是行
,相同的字段的有一个或多个行的数据
-
拿到了这个
字段的行
之后,然后再在这些行中对某个字段
使用分组函数
分组和分组函数的配合使用
-
要知道,如果单单使用分组函数 , 会作用到整个列上
-
如果是使用了分组,然后使用分组函数 , 就是将分组函数作用到每个组
关于书写sql语句的步骤(单表的,以后会在后面总结多表连接的)
(因为喜欢先分组再判断条件,所以见谅)
考虑步骤就是根据上面我标的步骤来
select 写完之后,column不要先写
直接写应该在哪个表中
然后判断分组
判断条件是不是涉及到分组函数 , 如果有在having中,没有在where中
写where条件
写having条件
如果有排序先排序
最后写column
另外关于条件,既可以在where语句中,也可以在分组函数中,要判断好依据的条件在哪
其实分组函数中可以有的条件很少,就是那几个分组函数的返回值基础上的,很容易辨别 但是如果条件是根据分组函数来进行判断,就要涉及到having , 在having 里面才能使用分组函数作为条件,具体例子在下面有介绍
5.1.测试
-- 案例1:查询每个工种的最高工资
SELECT job_id , MAX(salary)
FROM employees
GROUP BY job_id;
-- 案例2:查询每个位置上的部门个数
SELECT location_id , count(department_id)
FROM departments
GROUP BY location_id;
-- 案例3:(添加筛选条件) 查询邮箱中包含a字符 , 每个部门的平均工资
SELECT department_id , AVG(salary)
FROM employees
where email like '%a%'
GROUP BY department_id;
-- 案例4:(添加筛选条件)查询有奖金的每个领导手下员工的最高工资
-- 根据上面的步骤来
/*
在employees表中
以manager_id分组
条件是有奖金的,显然不是和分组函数有关的
写where
没有排序
写colomns
*/
SELECT manager_id , MAX(salary)
FROM employees
WHERE commission_pct is not null
GROUP BY manager_id;
-- 案例5:(添加复杂的筛选条件)查询那个部门的员工的个数>2
/*
确认是employees表
确定是以部门分组
条件个数大于2 , 能统计个数的是count分组函数 , 所以应该在分组函数这边判断 , 所以用到having
没有where
写having
没有order by
写colomns
*/
SELECT department_id , COUNT(*) AS count
FROM employees
GROUP BY department_id
HAVING count >= 2;
-- 案例6:(添加复杂的筛选条件)查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
-- 最后一次分析
/*
在employees表中
GROUP BY 工种job_id
判断条件 有奖金是在where中, 最高工资只能是max分组函数,在having中
WHERE 中 有奖金
没有order by
写columns
*/
SELECT job_id , MAX(salary)
FROM employees
WHERE commission_pct is not null
GROUP BY job_id
-- 案例7:(添加复杂的筛选条件)查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个 , 以及最低工资
SELECT manager_id , MIN(salary)
FROM employees
WHERE manager_id > 102
GROUP BY manager_id
HAVING MIN(salary) > 5000;
-- 案例8:(group by后面跟表达式) 以姓名的长度分组 , 输出相同长度的姓名的平均薪资
-- 案例9:(多组并且和order by一起使用) 查询每个部门每个工种的平均工资,并以降序排列
-- 测试
-- 1.查询各个job_id的员工工资的最大值,最小值,平均值,总和,并按照job_id升序
SELECT MAX(salary) AS 最大值 , MIN(salary) AS 最小值 , AVG(salary) 平均值 , SUM(salary) 总和
FROM employees
GROUP BY job_id
ORDER BY job_id;
-- 2.查询员工最高工资和最低工资的差距
SELECT (MAX(salary) - MIN(salary)) AS 'DIFFERENCE'
FROM employees;
-- 3.查询所有部门编号,员工数目和平均工资值 , 并且按照平均工资降序
SELECT department_id AS 部门编号 , COUNT(*) AS 员工数目 , AVG(salary) AS 平均工资
FROM employees
GROUP BY department_id
ORDER BY AVG(salary) DESC;
-- 4.查询各个管理者手下员工的最低工资,其中最低工资不能少于6000 , 没有管理者的员工不计算在内
SELECT manager_id , MIN(salary)
FROM employees
WHERE manager_id is not NULL
GROUP BY manager_id
HAVING MIN(salary) >= 6000;
-- 5.选择具有各个job_id的员工人数
SELECT job_id , count(*)
FROM employees
WHERE job_id IS NOT NULL
GROUP BY job_id
通过上面的分析方法 , 类似的题都可以一步一步的写出来,而且能够保证错误率很少,毕竟逻辑在那里摆着了了。
上面肯定有的写的不对的地方,如果有的话,请指出,一起进步。