mysql多表查询 问题的引出(重点,难点)
说明 多表查询是指基于两个和两个以上的表查询.在实际应用中,查询单个表可能不能满足你的需求.
多表查询练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 SELECT * FROM salgradeSELECT * FROM empSELECT * FROM deptSELECT ename,sal,dname,emp.deptno FROM emp,dept WHERE emp.deptno= dept.deptnoSELECT ename,sal,dname,emp.deptno FROM emp,dept WHERE emp.deptno= dept.deptno AND emp.deptno= 10 SELECT ename,sal,grade FROM emp,salgrade WHERE sal >= losal AND sal<= hisal; SELECT ename,sal,dname,emp.deptno FROM emp,dept WHERE emp.deptno= dept.deptno ORDER BY emp.deptno DESC
自连接 自连接是指在同一张表的连接查询[将同一张表看做两张表].
1 2 3 4 5 6 7 8 9 10 11 12 SELECT * FROM empSELECT worker.ename AS '职员名' ,boss.ename AS '上级名' FROM emp worker,emp boss WHERE worker.mgr= boss.empno;
mysql表子查询 什么是子查询 子查询是指嵌入在其它 sql 语句中的 select 语句,也叫嵌套查询
单行子查询 单行子查询是指只返回一行数据的子查询语句
请思考:如何显示与 SMITH 同一部门的所有员工?
多行子查询 多行子查询指返回多行数据的子查询 ,使用关键字 in
如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号、但是不含10自己的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 SELECT deptno FROM emp WHERE ename= 'SMITH' SELECT * FROM emp WHERE deptno = ( SELECT deptno FROM emp WHERE ename= 'SMITH' )SELECT DISTINCT job FROM emp WHERE deptno= 10 ; SELECT ename,job,sal,deptno FROM emp WHERE job IN ( SELECT DISTINCT job FROM emp WHERE deptno= 10 )AND deptno != 10
在多行子查询中使用 all 操作符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 SELECT ename,sal,deptno FROM emp WHERE sal> ALL ( SELECT sal FROM emp WHERE deptno = 30 ) SELECT ename,sal,deptno FROM emp WHERE sal> ( SELECT MAX (sal) FROM emp WHERE deptno = 30 )
在多行子查询中使用 any 操作符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SELECT ename,sal,deptno FROM emp WHERE sal> ANY ( SELECT sal FROM emp WHERE deptno = 30 )SELECT ename,sal,deptno FROM emp WHERE sal> ( SELECT MIN (sal) FROM emp WHERE deptno = 30 )
多列子查询 多列子查询是指查询返回多个列数据的子查询语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 SELECT deptno,job FROM emp WHERE ename= 'ALLEN' SELECT * FROM emp WHERE (deptno,job)= ( SELECT deptno,job FROM emp WHERE ename= 'ALLEN' )AND ename != 'ALLEN' SELECT * FROM student WHERE (chinese,english,math)= ( SELECT chinese,english,math FROM student WHERE `name`= '宋江' );
在 from 子句中使用子查询 请思考:查找每个部门工资高于本部门平均工资的人的资料
这里要用到数据查询的小技巧,把一个子查询当作一个临时表使用 请思考:查找每个部门工资最高的人的详细资料
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 SELECT deptno,AVG (sal) FROM emp GROUP BY deptno SELECT ename,sal,temp.avg_sal,emp.deptno FROM emp,( SELECT deptno,AVG (sal) AS avg_sal FROM emp GROUP BY deptno )temp WHERE emp.deptno= temp.deptno AND emp.sal> temp.avg_sal SELECT ename,sal,temp.max_sal,emp.deptno FROM emp,( SELECT deptno,MAX (sal) AS max_sal FROM emp GROUP BY deptno )temp WHERE emp.deptno= temp.deptno AND emp.sal= temp.max_sal SELECT COUNT (* ),deptno FROM emp GROUP BY deptno SELECT dname,dept.deptno ,loc,tmp.per_num AS '人数' FROM dept,( SELECT COUNT (* ) AS per_num,deptno FROM emp GROUP BY deptno ) tmp WHERE tmp.deptno= dept.deptno SELECT tmp.* ,dname,loc FROM dept,( SELECT COUNT (* ) AS per_num,deptno FROM emp GROUP BY deptno ) tmp WHERE tmp.deptno= dept.deptno
表复制 自我复制数据(蠕虫复制) 有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据。
思考题:如何删除掉一张表重复记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 CREATE TABLE my_tab01( id INT , `name` VARCHAR (32 ), sal DOUBLE , job VARCHAR (32 ), deptno INT );DESC my_tab01SELECT * FROM my_tab01INSERT INTO my_tab01 (id,`name`,sal,job,deptno) SELECT empno,ename,sal,job,deptno FROM emp; INSERT INTO my_tab01 SELECT * FROM my_tab01; CREATE TABLE my_tab02 LIKE emp;DESC my_tab02; INSERT INTO my_tab02 SELECT * FROM emp; SELECT * FROM my_tab02;DROP TABLE my_tmpCREATE TABLE my_tmp LIKE my_tab02INSERT INTO my_tmp SELECT DISTINCT * FROM my_tab02DELETE FROM my_tab02INSERT INTO my_tab02 SELECT * FROM my_tmpDROP TABLE my_tmpSELECT * FROM my_tab02
合并查询 介绍 有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号union , union all
nuion all 该操作符用于取得两个结果集的并集。当使用该操作符时,不会取消重复行。 union 该操作赋与union all相似,但是会自动去掉结果集中重复行。 .1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SELECT ename,sal,job FROM emp WHERE sal> 2500 SELECT ename,sal,job FROM emp WHERE job= 'MANAGER' SELECT ename,sal,job FROM emp WHERE sal> 2500 UNION ALL SELECT ename,sal,job FROM emp WHERE job= 'MANAGER' SELECT ename,sal,job FROM emp WHERE sal> 2500 UNION SELECT ename,sal,job FROM emp WHERE job= 'MANAGER'
外连接 左外连接(如果左侧的表完全显示我们就说是左外连接) select...from 表1 left join 表2 on条件 [表1:左表 表2:右表] 右外连接(如果右侧的表完全显示我们就说是右外连接) select...from 表1 rigth join 表2 on条件 [表1:左表 表2:右表] -- 表stu --表exam
id name id grade
1 Jack 1 56
2 Tom 2 76
3 Kity 11 8
4 nono
使用左连接(显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 SELECT dname,ename,job FROM emp,dept WHERE emp.deptno= dept.deptno ORDER BY dname CREATE TABLE stu( id INT , `name` VARCHAR (32 ));INSERT INTO stu VALUES (1 ,'Jack' ),(2 ,'tom' ),(3 ,'kity' ),(4 ,'nono' );SELECT * FROM stu;CREATE TABLE exam( id INT , grade INT );INSERT INTO exam VALUES (1 ,56 ),(2 ,76 ),(11 ,8 );SELECT * FROM exam;SELECT `name`,stu.id,grade FROM stu,exam WHERE stu.id= exam.id; SELECT `name`,stu.id,grade FROM stu LEFT JOIN exam ON stu.id= exam.id; SELECT `name`,stu.id,grade FROM stu RIGHT JOIN exam ON stu.id= exam.id;
课堂练习 列出部门名称和这些部门的员工信息(名字和工作),同时列出那些没有员工的部门名。5min 1.使用左外连接实现
2.使用右外连接实现
1 2 3 4 5 6 7 8 9 10 11 SELECT dname,ename,job FROM dept LEFT JOIN emp ON emp.deptno= dept.deptnoSELECT dname,ename,job FROM emp RIGHT JOIN dept ON emp.deptno= dept.deptno