MySQL-多表查询

1. 简介

含义:又称连接查询,当查询的字段来自于多个表时,就会用到连接查询

2.笛卡尔现象

笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行

  • 发生原因:没有有效的连接条件
  • 如何避免:添加有效的连接条件

3.分类

按年代分

  • sql92标准:仅仅支持内连接
  • sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接

按功能分

  • 内连接
    • 等值连接
    • 非等值连接
    • 自连接
  • 外连接
    • 左外连接
    • 右外连接
    • 全外连接
  • 交叉连接

4.sql92标准

4.1 等值连接

  1. 多表等值连接的结果为多表的交集部分
  2. n表连接,至少需要n-1个连接条件
  3. 多表的顺序没有要求
  4. 一般需要为表起别名
  5. 可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

案例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`;
4.12 为表起别名
  1. 提高语句的简洁度
  2. 区分多个重名的字段

注意:如果为表起了别名之后,则查询的字段就不能使用原来的表名去限定

案例3:查询员工名、工种号、工种名

SELECT 
	e.last_name,e.job_id,j.job_title
FROM 
	employees  e,jobs j
WHERE 
	e.`job_id`=j.`job_id`;
4.13.两个表的顺序可调换

案例4:查询员工名、工种号、工种名

SELECT 
	e.last_name,e.job_id,j.job_title
FROM 
	jobs j,employees e
WHERE 
	e.`job_id`=j.`job_id`;
4.14 加筛选

案例5:查询有奖金的员工名、部门名

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;

案例6:查询城市名中第二个字符为o的部门名和城市名

SELECT 
	department_name,city
FROM 
	departments d,locations l
WHERE 
	d.`location_id` = l.`location_id`
	AND city LIKE '_o%';
4.15 加分组

案例1:查询每个城市的部门个数

SELECT 
	COUNT(*) 个数,city
FROM 
	departments d,locations l
WHERE 
	d.`location_id`=l.`location_id`
GROUP BY city;

#案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资

SELECT 
	department_name,d.`manager_id`,MIN(salary)
FROM 
	departments d,employees e
WHERE 
	d.`department_id`=e.`department_id`
AND 
	commission_pct IS NOT NULL
GROUP BY department_name,d.`manager_id`;
4.16 加排序

案例:查询每个工种的工种名和员工的个数,并且按员工个数降序

SELECT 
	job_title,COUNT(*)
FROM 
	employees e,jobs j
WHERE 
	e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;
4.17 实现三表连接

案例:查询员工名、部门名和所在的城市

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`
AND 
city LIKE 's%'
ORDER BY department_name DESC;

4.2 非等值连接

含义:连接条件不是使用等号的称为非等值连接

案例1:查询员工的工资和工资级别
分析:员工表 employees与职绩表job_grades没有相同的字段进行连接,唯一有关系的就是工资,那么我们使用非等值连接进行查询。

SELECT 
	salary,grade_level
FROM 
	employees e,job_grades g
WHERE 
	salary BETWEEN g.`lowest_sal` AND g.`highest_sal`

4.3 自连接

含义:自连接可以理解为自己连接自己,在一张表上面所进行的操作;将一张表分成两张结构和数据完全一样的表

案例:查询员工名和上级的名称
分析:由于员工名与上级名都在 employees表中,上级本质上也是员工,所以使用自连接。

SELECT 
e.employee_id,e.last_name,m.employee_id,m.last_name
FROM 
employees e,employees m
WHERE 
e.`manager_id`=m.`employee_id`;

5.sql99标准

语法
select 查询列表
from 表1 别名 【连接类型】
join 表2 别名
on 连接条件
【where筛选条件】
【group by 分组】
【having 筛选条件】
【order by 排序列表】

分类

  • 内连接:inner
  • 外连接
    • 左外连接 :left 【outer】
    • 右外连接:right 【outer】
    • 全外连接:full【outer】
  • 交叉连接:cross

5.1内连接

语法:

select 
	查询列表
from1 别名
inner join2 别名
on 连接条件
where 筛选条件;

特点

  1. 添加排序、分组、筛选
  2. inner可以省略
  3. 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
  4. inner join连接和sql92语法的等值连接效果是一样的,都是查询多表的交集
5.11等值连接

案例1.查询员工名、部门名

SELECT 
	last_name,department_name
FROM 
	departments d
INNER JOIN  
	employees e
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的部门名和员工个数,并按个数降序(添加排序)

#1.查询每个部门的员工个数
SELECT 
	COUNT(*),department_name
FROM 
	employees e
INNER JOIN 
	departments d
ON 
	e.`department_id`=d.`department_id`
GROUP BY department_name

在①结果上筛选员工个数>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;

案例5.查询员工名、部门名、工种名,并按部门名降序(添加三表连接)

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;
5.12 非等值连接

查询员工的工资级别

SELECT salary,grade_level
FROM employees e
 JOIN job_grades g
 ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`;

查询工资级别的个数>20的个数,并且按工资级别降序

SELECT 
	COUNT(*),grade_level
FROM 
	employees e
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;
5.13 自连接

案例1:查询员工的名字、上级的名字

 SELECT 
 	e.last_name,m.last_name
 FROM 
 	employees e
JOIN 
	employees m
ON e.`manager_id`= m.`employee_id`;

案例2:查询姓名中包含字符k的员工的名字、上级的名字

SELECT 
	e.last_name,m.last_name
FROM 
	employees e
JOIN 
	employees m
ON 
	e.`manager_id`= m.`employee_id`
WHERE e.`last_name` LIKE '%k%';

5.2外连接

应用场景:用于查询一个表中有,另一个表没有的记录

特点:

  • 外连接的查询结果为主表中的所有记录
    • 如果从表中有和它匹配的,则显示匹配的值
    • 如果从表中没有和它匹配的,则显示null
    • 外连接查询结果=内连接结果+主表中有而从表没有的记录
  • 左外连接,left join左边的是主表
  • 右外连接,right join右边的是主表
  • 左外和右外交换两个表的顺序,可以实现同样的效果
  • 全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的

案例1:查询哪个部门没有员工

 #左外
SELECT 
	d.*,e.employee_id
FROM
	departments d
LEFT OUTER JOIN 
	employees e
ON 
	d.`department_id` = e.`department_id`
WHERE 
	e.`employee_id` IS NULL;
#右外
SELECT 
	d.*,e.employee_id
FROM 
	employees e
RIGHT OUTER JOIN 
	departments d
ON 
	d.`department_id` = e.`department_id`
WHERE 
	e.`employee_id` IS NULL;

全外连接

全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的

 USE girls;
 SELECT 
 	b.*,bo.*
 FROM 
 	beauty b
 FULL OUTER JOIN 
 	boys bo
 ON 
 	b.`boyfriend_id` = bo.id;

交叉连接(笛卡尔乘积)

 SELECT b.*,bo.*
 FROM beauty b
 CROSS JOIN boys bo;

6.sql92和 sql99pk

  • 功能:sql99支持的较多
  • 可读性:sql99实现连接条件和筛选条件的分离,可读性较高
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cycyong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值