5、多表查询

目录

00、多表查询

01、合并结果集:UNION、UNION ALL

1、UNION:去除重复记录

2、UNION ALL:不去除重复记录

02、连接查询 

(1)连接查询

(2)内连接

(3)外连接

(4)自然连接

03、子查询

3.1 工资高于JONES的员工

3.2 查询与SCOTT同一个部门的员工

3.3 工资高于30号部门所有人的员工信息

3.4 查询工作和工资与MARTIN(马丁)完全相同的员工信息

3.5 有2个以上直接下属的员工信息

3.6 查询员工编号为7788的员工名称、员工工资、部门名称、部门地址

自连接:自己连接自己,起别名

3.7 求7369员工编号、姓名、经理编号和经理姓名

3.8 求各个部门薪水最高的员工所有信息


00、多表查询

多表查询有如下几种:
        1、合并结果集;UNION、UNION ALL
        2、连接查询
                2.1 内连接  [INNER] JOIN  ON 
                2.2 外连接  OUTER JOIN ON
                        左外连接 LEFT [OUTER] JOIN
                        右外连接 RIGHT [OUTER] JOIN
                        全外连接(MySQL不支持)FULL JOIN
                2.3 自然连接  NATURAL JOIN
        3、子查询

01、合并结果集:UNION、UNION ALL

(1)作用:合并结果集就是把两个select语句的查询结果合并到一起!
(2)合并结果集有两种方式:
        UNION:去除重复记录
        UNION ALL:不去除重复记录
(3)被合并的两个结果:列数、列类型必须相同。

        前提:创建数据表t1和t2:

#创建数据表t1和t2
#(1)创建数据表t1,并插入数据
CREATE TABLE t1(
`a` INT,
`b` VARCHAR(10)
);
INSERT INTO t1 VALUES(1,'a'),(2,'b'),(3,'c'),(4,'d');
DELETE FROM t1 

#(1)创建数据表t2,并插入数据
DROP TABLE t2;
CREATE TABLE t2(
`c` INT,
`d` VARCHAR(10)
);
INSERT INTO t2 VALUES(4,'d'),(5,'e'),(6,'g');

1、UNION:去除重复记录

#(1)UNION:去除重复记录
SELECT * FROM t1
UNION
SELECT * FROM t2

-->最终结果:
mysql> SELECT * FROM t1
    -> UNION
    -> SELECT * FROM t2;
+------+------+
| a    | b    |
+------+------+
|    1 | a    |
|    2 | b    |
|    3 | c    |
|    4 | d    |
|    5 | e    |
|    6 | g    |
+------+------+

2、UNION ALL:不去除重复记录

(2)UNION ALL:不去除重复记录
SELECT * FROM t1
UNION ALL
SELECT * FROM t2

-->最终结果
mysql> SELECT * FROM t1
    -> UNION ALL
    -> SELECT * FROM t2;
+------+------+
| a    | b    |
+------+------+
|    1 | a    |
|    2 | b    |
|    3 | c    |
|    4 | d    |
|    4 | d    |
|    5 | e    |
|    6 | g    |
+------+------+

02、连接查询 

         连接查询就是求出多个表的乘积,例如t1连接t2,那么查询出的结果就是t1*t2。

        连接查询会产生笛卡尔积,也就是会产生很多错误信息,需要进行过滤,通过主外键关系进行过滤、

(1)连接查询

(2)内连接

(3)外连接

(4)自然连接

#2.连接查询:
/*
   连接查询会产生笛卡尔积,也就是会产生很多错误信息,需要进行过滤,通过主外键关系进行过滤

*/
#创建数据表t1、t2,并插入数据,进行如下连接查询
#产生t1*t2数据
SELECT * FROM t1,t2;
#操作emp dept
SELECT * FROM emp,dept;

#使用主外键关系做为条件来去除无用信息
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
#上面查询结果会把两张表的所有列都查询出来,也许你不需要那么多列,这时就可以指定要查询的列了。
SELECT emp.empno,emp.ename,emp.sal,dept.deptno,dept.loc FROM emp,dept WHERE emp.deptno=dept.deptno;
#给表取别名:
SELECT e.empno,e.ename,e.sal,d.deptno,d.loc FROM emp e,dept d WHERE e.deptno=d.deptno;

#2.1 内连接
/*
    内连接的特点:查询结果必须满足条件。例如我们向emp表中插入一条记录:
	1015 张三 保洁员 1009 1999-12-31 80000.00 50
    其中deptno为50,而在dept表中只有10、20、30、40部门,那么上面的查询
    结果中就不会出现“张三”这条记录,因为它不能满足e.deptno=d.deptno这个条件。
*/
#内连接标准语句:内连接不会显示不满足条件的记录
SELECT * FROM emp e INNER JOIN dept d ON e.deptno=d.deptno;

#使用之前在emp表中再添加一行数据:
#2.2 外连接:会显示不满足条件的记录
#(1)左外连接:先查询出左表的所有数据,然后去查询右表,右表中满足的数据显示,不满足的显示NULL
SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno=d.deptno;
#(2)右外连接:先查询出右表的所有数据,然后去查询左表,左表中满足的数据显示,不满足的显示NULL
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno=d.deptno;

#2.3 自然连接:自动找到过滤条件去除笛卡尔积里无用的数据
#自然内连接
SELECT * FROM emp NATURAL JOIN dept;
#自然左外连接
SELECT * FROM emp NATURAL LEFT JOIN dept; 
#自然右外连接
SELECT * FROM emp NATURAL RIGHT JOIN dept;

03、子查询

        子查询(嵌套查询):一个select语句中包含另一个完整的select语句

3.1 工资高于JONES的员工

#3.1 工资高于JONES的员工
#第一步:查询JONES的工资 -->2975
SELECT sal FROM emp WHERE `ename`='JONES';
#第二步:查询工资大于2975的员工记录
SELECT * FROM emp WHERE `sal`>2975;
#合并写
SELECT * FROM emp WHERE `sal`>(SELECT sal FROM emp WHERE `ename`='JONES');

-->最终结果:
mysql> SELECT * FROM emp WHERE `sal`>(SELECT sal FROM emp WHERE `ename`='JONES');
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job       | mgr  | hiredate   | sal     | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7788 | SCOTT | ANALYST   | 7566 | 1987-04-19 | 3000.00 | NULL |     20 |
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
|  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
+-------+-------+-----------+------+------------+---------+------+--------+

3.2 查询与SCOTT同一个部门的员工

#3.2 查询与SCOTT同一个部门的员工
#第一步:查询SCOTT的部门编号 -->20
SELECT deptno FROM emp WHERE `ename`='SCOTT';
#第二步:查询部门编号为20的员工记录
SELECT * FROM emp WHERE `deptno`=20;
#合并写
SELECT * FROM emp WHERE `deptno`=(SELECT deptno FROM emp WHERE `ename`='SCOTT');

-->最终结果:
mysql> SELECT * FROM emp WHERE `deptno`=(SELECT deptno FROM emp WHERE `ename`='SCOTT');
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job     | mgr  | hiredate   | sal     | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
|  7369 | SMITH | CLERK   | 7902 | 1980-12-17 |  800.00 | NULL |     20 |
|  7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL |     20 |
|  7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL |     20 |
|  7876 | ADAMS | CLERK   | 7788 | 1987-05-23 | 1100.00 | NULL |     20 |
|  7902 | FORD  | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
+-------+-------+---------+------+------------+---------+------+--------+

3.3 工资高于30号部门所有人的员工信息

#3.3 工资高于30号部门所有人的员工信息
#第一步:先求出30号部门的最高工资-->2850
SELECT MAX(sal) FROM emp WHERE `deptno`=30;
#第二步:工资高于30号部门所有人的员工信息
SELECT * FROM emp WHERE `sal`>2850;
#合并写:
SELECT * FROM emp WHERE `sal`>(SELECT MAX(sal) FROM emp WHERE `deptno`=30);
#另一种写法
SELECT * FROM emp WHERE `sal`>ALL(SELECT MAX(sal) FROM emp WHERE `deptno`=30);

-->最终结果:
mysql> SELECT * FROM emp WHERE `sal`>(SELECT MAX(sal) FROM emp WHERE `deptno`=30);
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job       | mgr  | hiredate   | sal     | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7566 | JONES | MANAGER   | 7839 | 1981-04-02 | 2975.00 | NULL |     20 |
|  7788 | SCOTT | ANALYST   | 7566 | 1987-04-19 | 3000.00 | NULL |     20 |
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
|  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
+-------+-------+-----------+------+------------+---------+------+--------+

3.4 查询工作和工资与MARTIN(马丁)完全相同的员工信息

#3.4 查询工作和工资与MARTIN(马丁)完全相同的员工信息
#第一步:查询MARTIN的工作和工资 -->
SELECT job,sal FROM emp WHERE `ename`='MARTIN';
#第二步:查询工作和工资与MARTIN(马丁)完全相同的员工信息
SELECT * FROM emp WHERE `job`='SALESMAN' AND `sal`=1250.00;
#合并写
SELECT * FROM emp WHERE (job,sal) 
IN(SELECT job,sal FROM emp WHERE `ename`='MARTIN');

-->最终结果:
mysql> SELECT * FROM emp WHERE (job,sal)
    -> IN(SELECT job,sal FROM emp WHERE `ename`='MARTIN');
+-------+--------+----------+------+------------+---------+---------+--------+
| empno | ename  | job      | mgr  | hiredate   | sal     | comm    | deptno |
+-------+--------+----------+------+------------+---------+---------+--------+
|  7521 | WARD   | SALESMAN | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
+-------+--------+----------+------+------------+---------+---------+--------+

3.5 有2个以上直接下属的员工信息

#3.5 有2个以上直接下属的员工信息
#第一步:首先查询出mgr出现两次以上-->7698 7839
SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>2
#第二步:有2个以上直接下属的员工信息
SELECT * FROM emp WHERE `empno`=7698 OR `empno`=7839;
#合并写
SELECT * FROM emp WHERE empno IN(SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>2);

-->最终结果:
mysql> SELECT * FROM emp WHERE empno IN(SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>2);
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job       | mgr  | hiredate   | sal     | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7698 | BLAKE | MANAGER   | 7839 | 1981-05-01 | 2850.00 | NULL |     30 |
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
+-------+-------+-----------+------+------------+---------+------+--------+

3.6 查询员工编号为7788的员工名称、员工工资、部门名称、部门地址

#3.6 查询员工编号为7788的员工名称、员工工资、部门名称、部门地址
SELECT ename,sal,dname,loc FROM emp,dept WHERE emp.deptno=dept.deptno AND empno=7788
#现在dept这个表中只有3列,并且这3列都是我们需要用到的。假如dept这个表有100列,我们只需要其中deptno、dname、loc这3列,那么我们在from后面可以使用子查询
SELECT e.ename,e.sal,d.dname,d.loc
FROM emp e,(SELECT dname,loc,deptno FROM dept)d
WHERE e.deptno=d.deptno AND e.empno=7788

-->最终结果;
mysql> SELECT e.ename,e.sal,d.dname,d.loc
    -> FROM emp e,(SELECT dname,loc,deptno FROM dept)d
    -> WHERE e.deptno=d.deptno AND e.empno=7788;
+-------+---------+----------+--------+
| ename | sal     | dname    | loc    |
+-------+---------+----------+--------+
| SCOTT | 3000.00 | RESEARCH | DALLAS |
+-------+---------+----------+--------+

自连接:自己连接自己,起别名

3.7 求7369员工编号、姓名、经理编号和经理姓名

#3.7 求7369员工编号、姓名、经理编号和经理姓名
SELECT empno,ename,mgr,ename FROM emp WHERE empno=7369
SELECT ename FROM emp WHERE empno=7902 #根据求得的经理编号得到经理姓名


SELECT e1.empno AS '员工编号',e1.ename AS '员工姓名',e1.mgr '员工的经理编号',e2.ename AS '员工的经理姓名' FROM emp e1,emp e2 
WHERE e1.empno=7369 AND e1.mgr=e2.empno

-->最终结果:
mysql> SELECT e1.empno AS '员工编号',e1.ename AS '员工姓名',e1.mgr '员工的经理编号',e2.ename AS '员工的经理姓名' FROM emp e1,emp e2
    -> WHERE e1.empno=7369 AND e1.mgr=e2.empno;
+----------+----------+----------------+----------------+
| 员工编号 | 员工姓名 | 员工的经理编号 | 员工的经理姓名 |
+----------+----------+----------------+----------------+
|     7369 | SMITH    |           7902 | FORD           |
+----------+----------+----------------+----------------+

3.8 求各个部门薪水最高的员工所有信息

#3.7.2 求各个部门薪水最高的员工所有信息
#根据部门编号求出各个部门对应的最高工资
SELECT deptno,MAX(sal) FROM emp GROUP BY deptno;
#不够严谨:各个部门薪水最高的员工所有信息
SELECT * FROM emp WHERE sal=5000 OR sal=3000 OR sal=2850 OR sal=1200;
SELECT * FROM emp WHERE sal IN(SELECT MAX(sal) FROM emp GROUP BY deptno)
#推荐使用下述命令:严谨
SELECT e1.* FROM emp e1,(SELECT MAX(sal) maxsal,deptno FROM emp GROUP BY deptno)d
WHERE e1.sal=d.maxsal AND e1.deptno=d.deptno;

-->最终结果
mysql> SELECT e1.* FROM emp e1,(SELECT MAX(sal) maxsal,deptno FROM emp GROUP BY deptno)d
    -> WHERE e1.sal=d.maxsal AND e1.deptno=d.deptno;;
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job       | mgr  | hiredate   | sal     | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7698 | BLAKE | MANAGER   | 7839 | 1981-05-01 | 2850.00 | NULL |     30 |
|  7788 | SCOTT | ANALYST   | 7566 | 1987-04-19 | 3000.00 | NULL |     20 |
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
|  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
|  7988 | LISA  | 保洁      | 7782 | 2022-07-22 | 1200.00 | NULL |     50 |
+-------+-------+-----------+------+------------+---------+------+--------+

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小猪VS恒哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值