MySQL学习笔记(四)——分组函数,分组查询,链接查询
做者:就叫易易好了
日期:2020/11/18
1、分组函数
功能:用做统计使用,又称为聚合函数或统计函数mysql
分类:web
sum函数
avg函数
max函数
min函数
count函数
如下代码演示均基于myemployees数据库,可在MySQL学习笔记(一)中下载sql
#简单的使用案例
SELECT SUM(salary) FROM employees;
做用:求employees表中全部员工的薪水之和
SELECT avg(salary) FROM employees;
做用:求employees表中全部员工薪水的平均值
SELECT max(salary) FROM employees;
做用:求employees表中全部员工的薪水的最大值
SELECT min(salary) FROM employees;
做用:求employees表中全部员工的薪水的最小值
SELECT count(salary) FROM employees;
做用:求salary这个字段的非空值的个数
特色:数据库
sum,avg通常用于处理数据类型
max,min,count能够处理任何类型
sum,avg,max,min,count都忽略null值
#与distinct函数搭配使用
SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
返回值后者要比前者大不少,由于distinct是去重函数,去掉了表格里面不少重复的值
对于count函数的详细介绍
SELECT (*) FROM employees;svg
在统计的过程当中,该行只要用一个值不为null,就能统计上函数
此语句常常用来统计全部行数的个数,通常用这个语句统计总行数学习
2、分组查询
若是咱们要查询employees表格中各部门的平均工资该怎么办呢?这个时候就须要使用分组查询了。code
group by 语句
语法:xml
select 分组函数blog
from 表
where 筛选条件
group by 分组的列表
查询列表必须特殊,要求是分组函数和group by后出现的字段。
#案例:查询每一个工种的最高工资
SELECT MAX(salary),jio_id
FROM employees
GROUP BY job_id
#案例:查询每一个位置上的部门个数
SELECT COUNT(*),location_id
FROM departments
GROUP BY
location_id;
一、添加筛选条件
#案例1:查询邮件中包含a的字符的,每一个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE
email like '%a%'
GROUP BY
department_id;
#案例2:查询有奖金的每一个领导手下员工的最高工资
SELECT
MAX(salary),manager_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
manager_id;
二、添加复杂的筛选条件
#案例1:查询哪一个部门的员工个数>2
思路:
·先查询每一个部门的员工个数
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id;
·根据上面的结果,出啊讯那个部门的员工个数>2
这个时候就须要有一个函数来链接上面的语句了
此时咱们是用HAVING
也就是:
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
#案例2:查询每一个工种有奖金的员工最高工资>12000的工种编号和最高工资
思路:先查询每一个工种有奖金的员工最高工资和工种编号,
再查询最高工资大于12000的人
SELECT
MAX(salary),job_id
FROM
employees
GROUP BY
job_id;
HAVING
MAX(salary)>12000
#案例3:查询领导编号>102的每一个领导手下的最低工资>5000的领导编号是哪一个,以及最低工资
思路:查询领导编号>102的每一个领导手下的领导编号,再查询最低工资大于5000的人
SELECT
MIN(salary),manager_id
FROM
employees
WHERE
manager_id>102
GROUP BY
manager_id
HAVING
MIN(salary)>5000;
三、按表达式或函数分组
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
思路:先查询每一个长度的员工个数,
SELECT
COUNT(*),
LENGTH(last_name)
FROM
employees
GROUP BY
LENGTH(last_name)
HAVING
COUNT(*)>5;
四、按多个字段进行分组
#案例:查询每一个部门每一个工种的员工的平均工资
SELECT
AVG(salary),department_id,job_id
FROM
employees
GROUP BY
department_id,job_id;
五、添加排序
#案例:查询每一个部门每一个工种的员工的平均工资,而且按平均工资的高低显示
SELECT
AVG(salary),department_id,job_id
FROM
employees
GROUP BY
department_id,job_id
ORDER BY
AVG(salary) DESC;
3、链接查询
也就是多表查询,当查询的数据来自于多个表的时候,就会用到链接查询
笛卡尔乘积现象:表A有m行,表B有n行,笛卡尔乘积的结果有m*n行
beauty表:
boys表:
若是执行如下语句:
SELECT name,boyname
FROM boys,bueaty;
获得的即是:
显然……(You Know)
出现这样的缘由是没有有效的链接条件,这个时候咱们须要添加有效的链接条件才能够避免这种尴尬的事情发生。
分类:
按年代分类
sq192标准:仅仅支持内链接
sq199标准:支持全部内链接+外链接(左外和右外)+交叉链接
按功能分类
内链接
等值链接
非等值链接
自链接
外链接
左外链接
右外链接
全外链接
交叉连结
一、sq192标准
1.1 等值链接
#案例1:查询女神名和对应的男神名
SELECT NAME,boyName
FROM boys,beauty
WHERE beauty.boyfriend_id=boys.id;
#案例2:查询员工名和对应的部门名
SELECT last_name,department_name
FROM employees,departments
WHERE employees.`department_id`=departments.`department_id`;
#案例3:为表取别名,提升语句简洁度,区分多个重名字段
查询员工名,工种号,工种名
SELECT last_name,e.job_id,job_title
FROM employees AS e,jobs
WHERE e.`job_id`=jobs.`job_id`;
注意:若是取了别名,查询的字段就不能使用原来的表名去限定
FROM语句中表格的顺序能够互换
#案例4:查询有奖金的员工名,部门名
SELECT last_name,department_name,commission_pct
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;
#案例5:查询城市名中第二个字符为O的部门名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
AND city like '_o%';
加入分组
#案例6:查询每一个城市的部门个数
SELECT COUNT(*) 个数,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;
加入排序
#案例7:查询每一个工种的工种名和员工个数,而且按员工个数降序排列
SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;
实现三表链接
#案例8:查询员工名,部门名和所在的城市
SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`;
1.2 非等值链接
咱们先创建一个等级表:
CREATE TABLE job_grades
(grade_level VARCHAR(3),
lowest_sat INT,
highest_sal INT);
INSERT INTO job_grades
VALUES('A',1000,2999);
INSERT INTO job_grades
VALUES('B',3000,5999);
INSERT INTO job_grades
VALUES('C',6000,9999);
INSERT INTO job_grades
VALUES('D',10000,14999);
INSERT INTO job_grades
VALUES('E',15000,24999);
INSERT INTO job_grades
VALUES('F',25000,40000);
样式以下:
#案例:查询员工的工资和工资等级
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`;
二、sql99语法
语法:
SELECT 查询列表
from 表1 别名 【链接类型】
join 表2 别名
on 链接条件
where 筛选条件
group by 分组
having 筛选条件
order by 排序列表
(提升了可读性,实现了分离)
分类
内链接:inner
外链接
左外:left [outer]
右外:right[outer]
全外:full [outer]
交叉链接:cross
内链接
语法:
select 查询列表
from 表1 别名
inner join 表2 别名
on链接条件;
等值链接:
#案例1:查询员工名,部门名
SELECT last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`;
添加筛选
#案例2:查询名字中包含e的员工名和工种名
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.`job_id`=j.`job_id`
WHERE e.`last_name` LIKE '%e%';
添加分组+筛选
#案例3:查询部门个数>3的城市名和部门个数
SELECT city,COUNT(*) 部门个数
FROM departments d
INNER JOIN locations l
ON d.`location_id`=l.`location_id`
GROUP BY city
HAVING count(*)>3;
添加分组+筛选+排序
#案例4:查询哪一个部门的员工个数>3的部门名和员工个数,并按个数降序
SELECT COUNT(*),department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
GROUP BY department_name
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;
多表链接
#案例:查询员工名、部门名、工种名、并部门名降序排列
SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`
INNER JOIN jobs j
ON e.`job_id`=j.`job_id`
ORDER BY department_name DESC;
非等值链接
#案例1:查询员工的工资级别
SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades g
ON salary between g.`lowest_sal` AND g.`highest_sal`;
#案例2:查询工资级别的个数>20的个数,而且按工资级别降序
SELECT COUNT(*),grade_level
FROM employees e
INNER JOIN job_grades g
ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
GROUP BY grade_level
HAVING COUNT(*)>20
ORDER BY grade_level DESC;
自链接
#案例:查询员工的名字,上级的名字
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m
ON e.`manager_id`=m.`employee_id`;