当前位置:
首页 > temp > python入门教程 >
-
MYSQL——表相关操作(多表查询【联表查询&子查询】)
一、多表查询——多表联合查询
# 方案1:链表查询 把多张物理表合并成一张虚拟表,再进行后续查询 #======>内链接:保留两张表有对应关系的记录 select * from emp,dep where emp.dep_id=dep.id; select dep.name,emp.name from emp inner join dep on emp.dep_id=dep.id where dep.name = "技术"; #======>左链接:在内链接的基础上保留左表的记录 select * from emp left join dep on emp.dep_id=dep.id; #======>右链接:在内链接的基础上保留右表的记录 select * from emp right join dep on emp.dep_id=dep.id; #======>全外链接:在内链接的基础上保留左右表的记录 full join select * from emp left join dep on emp.dep_id=dep.id union select * from emp right join dep on emp.dep_id=dep.id; 示例1:查询所有部门名及对应的员工个数 select dep.name,count(emp.id) from emp right join dep on emp.dep_id = dep.id group by dep.name ; select dep.name,count(emp.id) from emp right join dep on emp.dep_id = dep.id group by dep.name having count(emp.id) < 2 ; #示例2:即找出年龄大于25岁的员工以及员工所在的部门 select emp.name,dep.name from emp inner join dep on emp.dep_id = dep.id where age > 25; #示例3:以内连接的方式查询employee和department表,并且以age字段的升序方式显示 # 把多张表链接到一起: select * from (select emp.*,dep.name as dep_name from emp inner join dep on emp.dep_id = dep.id) as t1 inner join dep on t1.dep_id = dep.id ; select * from emp inner join dep on emp.dep_id = dep.id inner join dep as t1 on t1.id = dep.id; # 查询部门内最新入职的员工 select * from employee inner join (select depart_id,max(hire_date) as maxd from employee group by depart_id) as t1 on employee.depart_id = t1.depart_id where employee.hire_date = t1.maxd ;
二、多表查询——子查询
# 方案2:子查询 从一张表中查询出结果,用该结果作为查 询下一张表的过滤条件 select * from employee where hire_date = (select max(hire_date) from employee); #查询平均年龄在25岁以上的部门名 select * from dep where id in (select dep_id from emp group by dep_id having avg(age) > 25); #查看技术部员工姓名 select * from emp where dep_id in (select id from dep where name="技术"); #查看不足1人的部门名(子查询得到的是有人的部门id) select * from dep where id not in (select distinct dep_id from emp); select * from dep where exists (select * from emp where id>3);
三、详细介绍子查询
1:子查询是将一个查询语句嵌套在另一个查询语句中。
2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
4:还可以包含比较运算符:= 、 !=、> 、<等
1、in关键字的子查询
# 1、in select * from emp where age=18 or age=38 or age=28; select * from emp where age in (18,38,28); # 子查询的思路 select * from emp where dep_id in (select id from dep where name="技术" or name="销售"); # 链表的思路 select * from emp inner join dep on emp.dep_id = dep.id where dep.name in ("技术","销售"); # not in不支持null mysql> select * from dep; +------+--------------+ | id | name | +------+--------------+ | 200 | 技术 | | 201 | 人力资源 | | 202 | 销售 | | 203 | 运营 | +------+--------------+ 4 rows in set (0.00 sec) mysql> insert into emp values(7,'lili','female',48,null); Query OK, 1 row affected (0.03 sec) mysql> select * from emp -> ; +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 1 | egon | male | 18 | 200 | | 2 | alex | female | 48 | 201 | | 3 | wupeiqi | male | 38 | 201 | | 4 | yuanhao | female | 28 | 202 | | 5 | liwenzhou | male | 18 | 200 | | 6 | jingliyang | female | 18 | 204 | | 7 | lili | female | 48 | NULL | +----+------------+--------+------+--------+ 7 rows in set (0.00 sec) mysql> 查询出有员工的部门, select * from dep where id in (select distinct dep_id from emp); 查询出没有员工的部门, select * from dep where id not in (select distinct dep_id from emp); select * from dep where id not in (select distinct dep_id from emp where dep_id is not null);
2、any 和 all关键字的子查询
# any后也跟子查询语句,与in不一样的地方在哪里 # in (子查询语句) # in (值1,值2,值3) # 而any只能跟子查询语句 # any必须跟比较运算符配合使用 select * from emp where dep_id in (select id from dep where name in ("技术","人力资源")); select * from emp where dep_id = any (select id from dep where name in ("技术","人力资源")); select * from emp where dep_id not in (select id from dep where name in ("技术","人力资源")); select * from emp where ! (dep_id = any(select id from dep where name in ("技术","人力资源"))); 查询出那些薪资比所有部门的平均薪资都高的员工=》薪资在所有部门平均线以上的狗币资本家 select * from employee where salary > all (select avg(salary) from employee where depart_id is not null group by depart_id); 查询出那些薪资比所有部门的平均薪资都低的员工=》薪资在所有部门平均线以下的无产阶级劳苦大众 select * from employee where salary < all (select avg(salary) from employee where depart_id is not null group by depart_id); 查询出那些薪资比任意一个部门的平均薪资高的员工=》薪资在任一部门平均线以上的员工 select * from employee where salary > any (select avg(salary) from employee where depart_id is not null group by depart_id); select * from employee where salary < any (select avg(salary) from employee where depart_id is not null group by depart_id);
3、exists关键字的子查询
ps:
exists (子查询语句,不能用集合体)
not exists底层用索引,以提升效率
not in即便是有索引也没有用,因为他要把所有的值都走一遍
not exists 效率高于not in,因为底层用索引原因
# exists 对比 in # in的效率 高于 exists in 先把子查询语句查出结果集再应用到外层里 exists在外层取一条记录,内层子查询语句都要执行一遍,所以叫相关子查询 select * from 表1 where exists (select * from 表2); # 例如:查询有员工的部门=》 select * from dep where exists (select * from emp where dep.id=emp.dep_id); # not exists的效果 高于 not in select * from dep where not exists (select * from emp where 203=emp.dep_id); # 例:查询选修了所有课程的学生id、name: # 实现方式一:选修了三门课程的学生就是选修了所有课程的学生 select s.id,s.name from student as s inner join student2course as sc on s.id = sc.sid group by sc.sid having count(sc.cid) = (select count(id) from course); # 实现方式二:找到这样的学生,该学生不存在没有选修过的课程 select * from student as s where not exists ( select * from course as c not exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); select * from student as s where not exists ( select * from course as c where not exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); 学生记录可以过滤出来,一定是子查询内没有记录 for 学生: # s.id=2 for 课程: # c.id=1 for 学生2课程: # sc.sid = 2 and sc.cid = 1 pass ================================== for sid in [1,2,3,4]: for cid in [1,2,3]: (sid,cid) 最外层循环一次 # (1,1) # (1,2) # (1,3) 最外层循环二次 # (2,1) # (2,2) # (2,3) 最外层循环三次 # (3,1) # (3,2) # (3,3) 最外层循环四次 # (4,1) # (4,2) # (4,3) =================================== # 例2、查询没有选择所有课程的学生,即没有全选的学生。=》找出这样的学生,存在没有选修过的课程 select * from student as s where exists ( select * from course as c where not exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); # 例3、查询一门课也没有选的学生=》找出这样的学生,不存在选修过的课程 select * from student as s where not exists ( select * from course as c where exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); # 例4、查询至少选修了一门课程的学生=》找出这样的学生,存在选修过课程 select * from student as s where exists ( select * from course as c where exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) );
4、in与exists的区别
!!!!!!当in和exists在查询效率上比较时,in查询的效率快于exists的查询效率!!!!!! ==============================exists============================== # exists exists后面一般都是子查询,后面的子查询被称做相关子查询(即与主语句相关),当子查询返回行数时,exists条件返回true, 否则返回false,exists是不返回列表的值的,exists只在乎括号里的数据能不能查找出来,是否存在这样的记录。 # 例 查询出那些班级里有学生的班级 select * from class where exists (select * from stu where stu.cid=class.id) # exists的执行原理为: 1、依次执行外部查询:即select * from class 2、然后为外部查询返回的每一行分别执行一次子查询:即(select * from stu where stu.cid=class.cid) 3、子查询如果返回行,则exists条件成立,条件成立则输出外部查询取出的那条记录 ==============================in============================== # in in后跟的都是子查询,in()后面的子查询 是返回结果集的 # 例 查询和所有女生年龄相同的男生 select * from stu where sex='男' and age in(select age from stu where sex='女') # in的执行原理为: in()的执行次序和exists()不一样,in()的子查询会先产生结果集, 然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.
5、带比较运算符的子查询
#比较运算符:=、!=、>、>=、<、<=、<> #查询大于所有人平均年龄的员工名与年龄 mysql> select name,age from emp where age > (select avg(age) from emp); +---------+------+ | name | age | +---------+------+ | alex | 48 | | wupeiqi | 38 | +---------+------+ 2 rows in set (0.00 sec) #查询大于部门内平均年龄的员工名、年龄 select t1.name,t1.age from emp t1 inner join (select dep_id,avg(age) avg_age from emp group by dep_id) t2 on t1.dep_id = t2.dep_id where t1.age > t2.avg_age;
出处:
https://www.cnblogs.com/guojieying/p/13629265.html
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数