MySQL--day5--多表查询

(以下内容全部来自上述课程)

多表查询

1. 为什么要用多表查询

sql 复制代码
# 如果不用多表查询
#查询员工名为'Abel'的人在哪个城市工作? 
SELECT*
FROM employees
WHERE last_name = 'Abel';

SELECT *
FROM departments
WHERE department_id = 80;

SELECT *
FROM locatipns
WHERE location_id=2500;

2. 多表查询如何实现

2.1 出现笛卡尔积错误

sql 复制代码
# 2. 出现笛卡尔积错误(交叉连接)
# 错误的实现方式:每个员工都与每个部门匹配了一遍。
# 错误原因:缺少了多表的连接条件 
SELECT employee_id,department_name
FROM employees,departments; # 查询出2889条记录

SELECT *
FROM employees; # 107条记录

SELECT 2889 / 107 
FROM DUAL;

SELECT *
FROM departments; # 27条记录

2.2 正确方式

sql 复制代码
#3.多表查询的正确方式:需要有连接条件
SELECT employee_id,department_name 
FROM employees,departments
#两个表的连接条件
WHERE employees.department_id = departments.department_id;

2.3 指明字段(优化)

sql 复制代码
#4.如果查询语句中出现了多个表中都存在的字段,则必须指明此字段所在的表。
SELECT employees.employee_id,departments.department_name, employees.department_id 
FROM employees,departments
WHERE employees.`department_id`= departments.department_id;
#建议:从sql优化的角度,建议多表查询时,每个字段前都指明其所在的表。

2.4 别名

sql 复制代码
#5.可以给表起别名,在SELECT和WHERE中使用表的别名。
SELECT emp.employee_id, dept.department_name, emp.department_id 
FROM employees emp,departments dept
WHERE emp.department_id = dept.department_id;

#如果给表起了别名,一旦在SELECT或WHERE中使用表名的话,则必须使用表的别名,而不能再使用表的原名。 
# 如下的操作是错误的:
SELECT emp.employee_id,departments.department_name,emp.department_id 
FROM employees emp,departments dept
WHERE emp.department_id = departments.department_id;

2.5 练习

sql 复制代码
#6.如果有n个表实现多表的查询,则需要至少n-1个连接条件
#练习:查询员工的employee_id,last_name,department_name,city
SELECT e.employee_id,e.last_name,d.department_name,l.city,e.department_id,l.location_id 
FROM employees e,departments d,locations l 
WHERE e.`department_id` = d.`department_id` 
AND d.`location_id`= l.`location_id`;

3. 多表查询的分类

3.1 等值连接 vs 非等值连接

上述例子都是等值连接

sql 复制代码
#非等值连接的例子: 
SELECT *
FROM job_grades;

SELECT e.last_name,e.salary,j.grade_level 
FROM employees e,job_grades j
#where e.`salary` between j.`lowest_sal` and j.`highest_sal`;
WHERE e.`salary`>= j.`lowest_sal` AND e.`salary` <= j.`highest_sal`;

3.2 自连接 vs 非自连接

sql 复制代码
#7.2 自连接	非自连接	
SELECT * 
FROM employees;

#自连接的例子:
#练习:查询员工id,员工姓名及其管理者的id和姓名
SELECT emp.employee_id,emp.last_name,mgr.employee_id,mgr.last_name 
FROM employees emp ,employees mgr
WHERE emp.'manager_id` = mgr.`employee_id`;

3.3 内连接 vs 外连接

sql 复制代码
#7.3内连接 vs外连接
# 内连接:合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行 
#        就是两表交集
SELECT employee_id,department_name 
FROM employees e,departments d
WHERE e.`department_id` = d.department_id; #只有106条记录

#外连接:合并具有同一列的两个以上的表的行,结果集中除了包含一个表与另一个表匹配的行之外,
#	    还查询到了左表或右表中不匹配的行。 
#       就是量表并集	
# 外连接的分类:左外连接(交集+e左部分)、右外连接(交集+d右部分)、满外连接(并集)具体看下方图片
# 查询"所有"就是外连接。

3.4 SQL92语法

sql 复制代码
#练习:查询所有的员工的last_name,department_name信息
SELECT employee_id, department_name 
FROM employees e,departments d
WHERE e.`department_id`= d.department_id;	# 需要使用左外连接	

#SQL92语法实现内连接:见上,略
#SQL92语法实现外连接:使用+ ----------MySQL不支持SQL92语法中外连接的写法!

# 左连接:左腿长右腿短,垫右腿
SELECT employee_id,department_name 
FROM employees e,departments d
WHERE e.`department_id` = d.department_id(+);

3.5 SQL99语法

sql 复制代码
#SQL99语法实现内连接:
SELECT last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;

#JOIN一个表ON一个条件
SELECT last_name,department_name,city 
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id` 
JOIN locations l
ON d.`location id` = l.`location id`;

#SQL99语法实现外连接:
#练习:查询所有的员工的last_name,department_name信息
# 左外连接:
SELECT last_name,department_name
FROM employees e LEFT JOIN departments d 
ON e.`department_id`= d.`department_id`;

#右外连接:
SELECT last_name,department_name
FROM employees e RIGHT JOIN departments d 
ON e.`department_id` = d.`department_id`;

#满外连接:mysql不支持FULL OUTER JOIN 
SELECT last_name,department_name
FROM employees e FULL OUTER JOIN departments d 
ON e.`department_id` = d.`department_id`;

4. SQL99的7种JOIN操作

4.1 UNION操作符

  • UNION ALL 比 UNION 多了一倍重叠的部分
  • 满外连接需要用UNION
  • 开发中能用UNION ALL的时候不用UNION
  • 无重复部分用UNION ALL效率更高

4.2 7种实现

sql 复制代码
#中图:内连接
SELECT employee_id,department_name 
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;

# 左上图:左外连接
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d 
ON e.`department_id` = d.`department_id`;

#右上图:右外连接
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d 
ON e.`department_id` = d.`departmentid`;
sql 复制代码
#左中图: 左上图+右null条件(中间挖出去)
SELECT employee_id, department_name
FROM employees e LEFT JOIN departments d 
ON e.`department_id`= d.`department_id` 

WHERE d.`department_id` IS NULL;

# 右中图: 右上图+左null条件(中间挖出去)
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d 
ON e.`department_id`= d.`department_id` 

WHERE e.`department_id` IS NULL;
sql 复制代码
#左下图:满外连接
# 方式1:左上图 UNION ALL 右中图
SELECT employee_id,department_name
FROM employees eI LEFT JOIN departments d 
ON e.`department id` = d.`department id` 

UNION ALL

SELECT employee_id,department_name
FROM employees eRIGHT JOIN departments d 
ON e.`department_id` = d.`department _id` 
WHERE e.`department_id` IS NULL;

# 方式2:左中图UNION ALL 右上图
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d 
ON e.`department_id` = d.`department_id` 
WHERE d.`department_id` IS NULL 

UNION ALL

SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d 
ON e.`department id` = d.`department id`;
sql 复制代码
# 右下图:左中图	UNION ALL 右中图	
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d 
ON e.`department_id` = d.`department_id` 
WHERE d.`department id` IS NULL 

UNION ALL

SELECT employee_id,department_name
FROM employees eRIGHT JOIN departments d 
ON e.`department_id`= d.`department_id` 
WHERE e.`department_id` IS NULL;

5. SQL99新特性

5.1 自然连接

sql 复制代码
#10. SQL99语法的新特性1:自然连接
SELECT employee_id,last_name,department_name 
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id` 
AND e.`manager_id` = d.`manager_id`;

SELECT employee_id,last_name,department_name 
FROM employees e NATURAL JOIN departments d;

5.2 USING连接

sql 复制代码
#11.SQL99语法的新特性2:USING
SELECT employee_id,last_name,department_name 
FROM employees e JOIN departments d 
ON e.department_id = d.department_id;

SELECT employee_id,last_name,department_name 
FROM employees e 
JOIN departments d
USING (department_id);	I
相关推荐
河铃旅鹿13 分钟前
Android开发-java版:Framgent
android·java·笔记·学习
不知更鸟1 小时前
Django 项目是什么
数据库·sqlite
有一个好名字4 小时前
MyBatis-Plus 三种数据库操作方式详解 + 常用方法大全
数据库·mybatis
-Xie-4 小时前
Redis(八)——多线程与单线程
java·数据库·redis
2501_916008894 小时前
手机抓包app大全:无需root的安卓抓包软件列表
android·ios·智能手机·小程序·uni-app·iphone·webview
抛砖者5 小时前
1、Ubuntu上MySQL安装,密码设置,远程访问,端口修改
mysql·ubuntu
G探险者5 小时前
为什么 VARCHAR(1000) 存不了 1000 个汉字? —— 详解主流数据库“字段长度”的底层差异
数据库·后端·mysql
百锦再5 小时前
第18章 高级特征
android·java·开发语言·后端·python·rust·django
gcygeeker5 小时前
安卓 4.4.2 电视盒子 ADB 设置应用开机自启动
android·adb·电视盒子
小驰行动派6 小时前
安卓上的极简番茄钟 | 开源
android·开源