当前位置:网站首页>记|一次exists关键字的学习记录

记|一次exists关键字的学习记录

2022-06-25 21:46:00 星星都掉了

那一天,和暑假说再见,和玩乐说拜拜,和自在说再会。
 
自己踏着清晨的阳光,迈着轻快的步伐,走在去新生报道处的路上,心里抑制不住的兴奋。往里面走,穿过一片不大的小树林,那片浅红色的楼宇就是宿舍楼,宿舍楼的东面就是学校的人工湖,建设的很大,布置的挺有格调。也正是因为有它的存在,让我在大学的这一段人生道路上,遍尝酸甜苦辣。
 
我希望在繁华尽处,寻一抹静谧,泛舟湖上,三五好友,一壶老酒,家人作伴,唱歌会友。来吧,于绿野间、阳光下创造美好,治愈青春。
 
也许那就是青春的样子。
 
不过现在想来,它依旧是那么美。
 
"同学,请借过一下"。"哦,不好意思",原来正好堵住了操场的北门口,新生报到处,就是从这里进去。有人拍了拍我的肩膀,"这位同学是来报到的吧?",一位外表俊朗的长者跟我说,
"嗯,是的",
"你是哪个系的呢?",
"计算机系",
“你叫什么名字啊?”,
"我叫王小风"。
"嗯,小风同学,我这有电脑,来帮我统计下新生报到的相关数据":
 
mysql 版本号:

 

CREATE TABLE `t_class` (`id` int unsigned NOT NULL AUTO_INCREMENT,`class_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '班级名称',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='班级名称表';
CREATE TABLE `t_student` (`id` int unsigned NOT NULL AUTO_INCREMENT,`user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '学生姓名',`age` int NOT NULL COMMENT '年龄',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表';
 
CREATE TABLE `t_class_student` (`id` int unsigned NOT NULL AUTO_INCREMENT,`student_id` int NOT NULL COMMENT '学生ID',`class_id` int NOT NULL COMMENT '班号',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='班级学生关联表';
INSERT INTO stu.t_student (user_name,age) VALUES('张依波',18),('李小蕊',19),('刘冷霜',18),('赵雨珍',17),('刘元蝶',19),('映雁',19),('宛秋',20),('刘高旻',19),('王昆雄',20),('赵星鹏',19);INSERT INTO stu.t_student (user_name,age) VALUES('高昆卉',18),('昊磊',18),('王小风',19);
INSERT INTO stu.t_class (class_name) VALUES('经贸系一班'),('医药系二班'),('外国语系A班'),('新闻系三班'),('园林旅游系一班'),('计算机系一班');
INSERT INTO stu.t_class_student (student_id,class_id) VALUES(1,1),(2,1),(3,2),(4,2),(5,2),(6,2),(7,3),(8,3),(9,4),(10,4);INSERT INTO stu.t_class_student (student_id,class_id) VALUES(13,6);
t_student是今年所有来报到的新生名单,包括已经报到还有未报到的学生。
 
已报到系别班级的学生名单:
select	id,	user_name as userName,	agefrom	stu.t_student as swhere	exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id);

 

 

未报到系别班级的学生名单:

select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as swhere	not exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id);

医药系二班已经报到的学生名单:

select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as swhere	exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id		and class_id = 2);

经贸系一班 和 外国语系A班已经报到的学生名单:

select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as swhere	exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id		and class_id in (1, 3));

已经报到的所有系别班级的学生名单:

select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as swhere	exists (	select		student_id	from		stu.t_class_student	where		1 = 1);

医药系二班并且年龄大于18岁的已经报到的学生名单:

select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as swhere	s.age > 18	and exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id		and class_id = 2);

【exists 和 in之间的比较】

执行流程:

先说关键字in,它要求查询的结果满足in后面括号中的条件,比如id、status等。它会先把in后面口号中的子查询sql执行完,然后根据拿到的结果再去执行前面主sql。

这个就类似于河水倒灌。比如降雨量大,就导致附近的河水量增多,因为积水路面的标高比河的水位线标高矮,河水就倒灌到雨水管里,然后形成路面积水。所以我把这种执行方法称为"倒灌执行法"。

而exists正好相反,是顺序执行,执行完exists前面的sql拿到结果结果后,要去主动和exists中的子查询sql去匹配,只有匹配成功的数据才可以返回到控制台。

EXPLAIN列的解释:

table:显示这一行的数据是关于哪张表的

type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、 indexhe和ALL

possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

key: 实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引

key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好

ref:显示索引的哪一列被使用了,如果可能的话,是一个常数

rows:MYSQL认为必须检查的用来返回请求数据的行数

Extra:关于MYSQL如何解析查询的额外信息。坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢

索引使用情况:

(一)查询所有系别班级已经报到的学生情况:

explain select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as s where s.id in (select id from stu.t_class_student tcs);

子查询用到索引,in没有用到

explain select	id,	user_name as userName,	agefrom	stu.t_student as swhere	exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id);

子查询用到索引,而外层sqlexists并没有用到索引

(二)查询所有系别班级未报到的学生情况:

explain select	s.id,	s.user_name as userName,	s.agefrom	stu.t_student as s where s.id not in (select id from stu.t_class_student tcs);

同样子查询用到索引,not in 关键字没有使用到索引

explain select	id,	user_name as userName,	agefrom	stu.t_student as swhere	not exists (	select		student_id	from		stu.t_class_student	where		student_id = s.id);

使用not exists 的也是一样的情况:子查询用到索引,not in 关键字没有使用到索引,走的全表扫描

【结束语】

翻山越岭只为一场遇见,全力以赴只为一次改变。答案就在眼泪里,也凝结在汗水中、感官和心灵。总有一样要生活在别处,你会更加坚定心中的热爱。

原网站

版权声明
本文为[星星都掉了]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/3146264/blog/5545216