当前位置:网站首页>MySQL基础 多表查询

MySQL基础 多表查询

2022-06-09 08:50:00 Maximize+

表与表之间总是存在关联,有一对多、多对多的关系。
在数据很多的时候,会将数据分散到多个表中,来减少不要必要的IO次数,用以提高查询速度和方便查询。
如果需要查询的数据多不同的表中,则形成了多表查询

#查找齐全信息,但是要通过三次SQL查询语句才可以实现
SELECT * FROM employees WHERE last_name = 'Abel';

SELECT*FROM departments WHERE department_id = 80;

SELECT*FROM locations WHERE location_id = 2500

笛卡尔积

如果数据库在进行多表查询时没有设置查询条件,则数据会交叉连接,也就是挨个去匹配,就导致了 一个表有5个数据 第二个表有 5个数据 就会出现 25条数据,而现在员工表有 107条记录 ,部门表有27条数据,没有设置查询条件就导致,数据进行了逐个匹配,产生了2889条记录。
在这里插入图片描述

这种错误的情况称为笛卡尔积错误。

正确的多表连接方式

#使用了表别名
SELECT emp.employee_id,des.department_name
FROM employees emp,departments des
WHERE emp.department_id = des.`department_id`;

因为有些字段会重名,所以建议每个字段都有专门的指定,比如像上面SELECT中的emp.employee_id,这样的写法效率也更快,系统不会去挨个遍历查找而是直接根据这个表去查找。
多表查询的逻辑实现:将想要查询的单独字段写在SELECT中并以逗号隔开,这与单表查询的写法大致相同,但是建议指定表,在FROM中将字段来源的表添加上,并可以使用表别名来更方便的查询,在WHERE中是连接条件,而多表之间也必定有字段相互关联,只有多表之间的数据有关联才可以进行明确的多表查询。

SELECT1字段,2字段,3字段...
FROM11别名,22别名,33别名...
WHERE1字段 =3字段...
SELECT emp.employee_id,des.department_name,emp.department_id
FROM employees emp,departments des
WHERE emp.department_id = des.`department_id`;

如果一个字段在多表中不是唯一的存在,如果不添加指定表就会报出不明确的错误,并且如果使用了表别名,表别名就会覆盖原来表名,此时在WHERE或SELECT中就必须使用表别名来作为调用对象。
在这里插入图片描述

#查询员工的编号,姓名,部门名,城市位置
SELECT t1.employee_id,t1.`last_name`,t2.`department_name`,t3.`city`
FROM employees t1,departments t2,locations t3
WHERE t1.`department_id` = t2.`department_id`
AND t2.`location_id` = t3.`location_id`;

非等值连接

有的时候数据的连接并非等值连接,而是非等值连接,这时候大部分要给一个区间来进行匹配

#根据非等值连接来筛选数据
#根据工资区间来筛选等级
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`;

自连接

有时候一个员工表中每个员工也有自己专属的管理者,而此时表如果想要查看员工的管理者则只能自己连接自己。

#自连接,通过经理id来进行连接
#员工的 manager_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;

内连接和外连接是什么

内连接指的就是只列举出满足条件的数据,而外连接是列举出不满足条件的数据
外连接也分三类
左外连接:左边表不满足条件的数据
右外连接:右边表不满足条件的数据
全外连接:全部不满足条的数据

写法实现

#SQL 92实现内连接 106条记录
SELECT e.`employee_id`,d.`department_name`
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`;

#SQL 92实现外连接
#SQL 92使用(+)来实现外连接
#但是SQL 92并不支持这样的写法,其他数据库支持
SELECT e.employee_id,d.department_name
FROM employees e,departments d
WHERE e.department_id=d.department_id(+);
#SQL 99使用 JOIN...ON来实现内连接
#SQL 99实现内连接
SELECT e.employee_id,d.department_name
FROM employees e JOIN departments d
ON e.department_id = d.`department_id`;

#添加另一个表的数据
#SQL 99实现内连接
#通过JOIN...ON的语句可以多次添加,可读性较高
SELECT e.employee_id,d.department_name,l.`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的左外、右外连接

#SQL 99实现左外连接
SELECT e.employee_id,d.department_name
FROM employees e LEFT JOIN departments d
ON e.department_id = d.`department_id`;
#SQL实现全外连接
#但是MySQL并不支持这种写法
SELECT e.employee_id,d.department_name
FROM employees e FULL JOIN departments d
ON e.department_id = d.`department_id`;

SQL 99实现 7种 JOIN操作

在这里插入图片描述

#内连接
SELECT e.`employee_id`,d.department_name
FROM employees e JOIN departments d
ON e.department_id = d.`department_id`;
#左外连接
SELECT e.`employee_id`,d.department_name
FROM employees e LEFT JOIN departments d
ON e.department_id = d.`department_id`;
#右外连接
SELECT e.`employee_id`,d.department_name
FROM employees e RIGHT JOIN departments d
ON e.department_id = d.`department_id`;
#只要左外连接
SELECT e.`employee_id`,d.`department_name`
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL;
#只要右外连接
SELECT e.`employee_id`,d.`department_name`
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`employee_id` IS NULL;
#实现满外连接
#方式一:左外连接和只要右外连接结合
SELECT e.`employee_id`,d.`department_name`
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
UNION ALL
SELECT e.employee_id,d.department_name
FROM employees e RIGHT JOIN departments d
ON e.department_id = d.department_id
WHERE e.employee_id IS NULL;
#方式二:右外连接和只要左外连接
SELECT e.`employee_id`,d.`department_name`
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
UNION ALL
SELECT e.`employee_id`,d.`department_name`
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL;
#只要左外和右外连接
SELECT e.`department_id`,d.`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 e.`employee_id`,d.`department_name`
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`employee_id` IS NULL;

自然连接

#下面两段代码效果完全一样
SELECT e.`employee_id`,e.last_name,d.`department_name`
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
AND e.`manager_id` = d.`manager_id`;
#sql 99的新特性 自然连接
#自然连接的特性是,会自动连接SQL92的等值连接
SELECT e.`employee_id`,e.last_name,d.`department_name`
FROM employees e NATURAL JOIN departments d;

USING连接

该关键字会自动去具有两个相同字段的表中自动查询数据,但是只使用于这种情况,如果是自连接的话是无法使用USING来进行替代的

#使用USING来代替 ON
SELECT e.`employee_id`,e.`last_name`,d.`department_name`
FROM employees e JOIN departments d
USING(department_id);

在这里插入图片描述
在这里插入图片描述

多表查询最后的练习

#显示所有员工的姓名,部门号和部门名称
SELECT e.`last_name`,e.`department_id`,d.`department_name`
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;

#查询90号部门员工的job_id和90号员工的location_id
SELECT e.`job_id`,d.location_id
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` = 90;

#选择所有有奖金的员工的last_name,department_name,location_id,city
SELECT e.last_name,e.`commission_pct`,d.department_name,d.location_id,l.city
#from employees e JOin departments d on e.`department_id` = d.`department_id`
FROM employees e LEFT JOIN departments d 
ON e.`department_id` = d.`department_id` 
LEFT JOIN locations l
ON d.`location_id` = l.`location_id`
WHERE e.`commission_pct` IS NOT NULL;

#选择city在Toronto工作的员工的 last_name,job_id,department_id,department_name
SELECT e.`last_name`,e.`job_id`,e.`department_id`,d.`department_name`
FROM employees e JOIN departments d
ON e.`department_id`=d.`department_id`
JOIN locations l ON d.`location_id`=l.`location_id`
WHERE l.`city` = 'Toronto';

#查询员工所在的部门名称、部门地址、姓名、工作,工资,其中员工所在的部门名称为 'Excecutive'
SELECT d.`department_name`,l.`street_address`,e.`last_name`,e.`job_id`,e.`salary`
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
LEFT JOIN locations l
ON d.`location_id`= l.location_id 
WHERE d.`department_name` = 'Executive';

#选定指定员工的姓名,员工号,以及他的管理者的姓名和员工号,类似于下面的格式
#select*from employees;
#employees EMP manager Mar
#kochhar 101 king 100
#MySQL99的内连接写法
SELECT t1.last_name "employees",t1.employee_id "EMP#",t2.last_name "manager",t2.employee_id "Mar#"
FROM employees t1 LEFT JOIN employees t2 
ON
t1.manager_id = t2.employee_id;

#查询哪些部门没有员工
SELECT d.`department_id`
FROM employees e  RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;

#查询哪个城市没有部门
SELECT l.`location_id`,l.`city`
FROM locations l LEFT JOIN departments d
ON d.`location_id`=l.`location_id`
WHERE d.`location_id` IS NULL;

#查询部门名为Sales 或 IT 的员工信息
SELECT d.`department_name`,e.*
FROM employees e JOIN departments d
ON d.`department_id` = e.`department_id`
#WHERE d.`department_name` = 'Sales' OR d.`department_name` = 'IT';
WHERE d.`department_name` IN ('Sales','IT');

再次总结7种JOINS实现

内连接和外连接的本质区别是,内连接是满足条件的数据,而外连接则是不满足条件的数据

  • ①内连接:通过 表1 JOIN 表2 ON 条件 来筛选,这里的数据为:只满足条件的数据。
  • ②左外连接:通过表1 LEFT JOIN 表2 ON条件来筛选,这里的数据为:满足条件的数据和不满足条件的左表(表1)数据
  • ③右外连接:通过表1 RINGHT JOIN 表2 ON条件来筛选,这里的数据为:只满足条件和不满足条件的右表(表2)数据
  • ④只要左外连接:通过表 1 RINGHT LEFT JOIN表 2NO条件来筛选,然后通过WHERE语句指定 左外连接指定数据为 IS NULL的数据,这里将只会显示左外连接的内容,不会显示内连接内容。
  • ⑤只要右外连接:通过表 1 RINGHT LEFT JOIN表 2NO条件来筛选,然后通过WHERE语句指定 右外连接指定数据为 IS NULL的数据,这里将只会显示右外连接的内容,不会显示内连接内容
  • ⑥全满连接(MySQL不支持的方式):通过表1 FULL JOIN 表2 ON条件来筛选,这里的数据为:所有满足条件和不满足条件的数据都筛选出来。
  • ⑥全满连接(MySQL支持的方式一通过左外连接和只要右外连接来实现):分两段代码,第一段代码为左外连接,最后一行的WHERE语句没有分号结尾,加上UNION ALL后加上只要右外连接的内容来拼接为全部满足条件和不满足条件的数据。
  • ⑥全满连接(MySQL支持的方式二通过右外连接和只要左外连接来实现):分两段代码,第一段代码为右外连接,最后一行的WHERE语句没有分号结尾,加上UNION ALL后加上只要左外连接的内容来拼接为全部满足条件和不满足条件的数据。
  • ⑦不要内连接:通过只要左外连接和只要右外连接的结果拼接一下就是不要内连接。
    在这里插入图片描述

关于七种JOISN的解析图

在这里插入图片描述

原网站

版权声明
本文为[Maximize+]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_55868059/article/details/125036628