当前位置:   article > 正文

mysql双层not exists查询执行流程_mysql not exist

mysql not exist

一、单个EXISTS、NOT EXISTS用法

  1. DROP TABLE IF EXISTS `t_staff`;
  2. CREATE TABLE `t_staff` (
  3. `id` int(11) NOT NULL,
  4. `name` varchar(255) DEFAULT NULL,
  5. PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='人员表';
  7. DROP TABLE IF EXISTS `t_major`;
  8. CREATE TABLE `t_major` (
  9. `id` int(11) NOT NULL,
  10. `staff_id` int(11) NOT NULL,
  11. `name` varchar(255) NOT NULL,
  12. PRIMARY KEY (`id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='技能表';
  14. INSERT INTO `t_staff` VALUES ('1', '张辽');
  15. INSERT INTO `t_staff` VALUES ('2', '赵云');
  16. INSERT INTO `t_staff` VALUES ('3', '夏侯渊');
  17. INSERT INTO `t_major` VALUES ('1', '2', '大鹏展翅');
  18. INSERT INTO `t_major` VALUES ('2', '2', '无敌风火轮');
  19. INSERT INTO `t_major` VALUES ('3', '3', '横扫千军');

 EXISTS内层查询【非空】外层的where返回【真值】;内层查询【为空】外层的where返回【假值】
NOT EXISTS内层查询【非空】外层的where返回【假值】;内层查询【为空】外层的where返回【真值】

SELECT * FROM t_student_course WHERE TRUE;     --  能查出数据
SELECT * FROM t_student_course WHERE FALSE;    -- 不能查出数据

1、查询至少有一个技能的人员信息(in、EXISTS)

  1. SELECT * FROM t_staff where id in (SELECT staff_id FROM t_major);
  2. SELECT * FROM t_staff where EXISTS (
  3. SELECT 1 from t_major where t_staff.id = t_major.staff_id
  4. );
  5. -- 赵云、夏侯渊

2、查询一个技能都没有的人员信息(in、EXISTS)

  1. SELECT * FROM t_staff where id not in (SELECT staff_id FROM t_major);
  2. SELECT * FROM t_staff where NOT EXISTS (
  3. SELECT 1 from t_major where t_staff.id = t_major.staff_id
  4. );
  5. -- 张辽

二、EXISTS、NOT EXISTS(3张表)

  1. DROP TABLE IF EXISTS `t_student`;
  2. CREATE TABLE `t_student` (
  3. `id` int(11) NOT NULL,
  4. `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  5. PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  7. DROP TABLE IF EXISTS `t_course`;
  8. CREATE TABLE `t_course` (
  9. `id` int(11) NOT NULL,
  10. `name` varchar(255) DEFAULT NULL COMMENT '课程名称',
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  13. DROP TABLE IF EXISTS `t_student_course`;
  14. CREATE TABLE `t_student_course` (
  15. `id` int(11) NOT NULL,
  16. `sid` varchar(255) NOT NULL,
  17. `cid` varchar(255) NOT NULL,
  18. `score` decimal(10,0) DEFAULT NULL,
  19. PRIMARY KEY (`id`)
  20. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  21. INSERT INTO `t_student` VALUES (1, '赵子龙');
  22. INSERT INTO `t_student` VALUES (2, '关羽');
  23. INSERT INTO `t_student` VALUES (3, '张飞');
  24. INSERT INTO `t_student` VALUES (4, '黄忠');
  25. INSERT INTO `t_student` VALUES (5, '马超');
  26. INSERT INTO `t_course` VALUES (1, '语文');
  27. INSERT INTO `t_course` VALUES (2, '数学');
  28. INSERT INTO `t_course` VALUES (3, '英语');
  29. INSERT INTO `t_student_course` VALUES (1, 1, 1, 95);
  30. INSERT INTO `t_student_course` VALUES (2, 1, 2, 99);
  31. INSERT INTO `t_student_course` VALUES (3, 1, 3, 100);
  32. INSERT INTO `t_student_course` VALUES (4, 2, 1, 99);
  33. INSERT INTO `t_student_course` VALUES (5, 2, 2, 100);
  34. INSERT INTO `t_student_course` VALUES (6, 3, 2, 100);
  35. INSERT INTO `t_student_course` VALUES (7, 3, 3, 95);
  36. INSERT INTO `t_student_course` VALUES (8, 4, 1, 100);

EXISTS和NOT EXISTS相关子查询什么时候返回,返回有两个条件(很重要)。

1、子查询找到一个匹配的立即返回;
2、子查询遍历所有,没有找到一个匹配的返回为空。

 1、查询出选修了全部课程的学生姓名

  1. SELECT name from t_student where id in(
  2. SELECT sid FROM t_student_course GROUP BY sid
  3. HAVING (count(sid)) = (SELECT count(*) from t_course)
  4. ) -- 记录一般写法
  5. SELECT name from t_student s where NOT EXISTS (
  6. SELECT 1 from t_course c where NOT EXISTS (
  7. SELECT 1 from t_student_course sc
  8. where sc.sid = s.id and sc.cid = c.id
  9. )
  10. )
  11. -- 赵子龙

 子查询只会返回true、false,select后面写1就行了。将查询语句定义成三个变量,后面好解释。

  1. let a1 = SELECT 1 from t_student_course sc
  2. where sc.sid = s.id and sc.cid = c.id
  3. let b1 = SELECT 1 FROM t_course WHERE NOT EXISTS (a1)
  4. let c1 = SELECT * FROM t_student WHERE NOT EXISTS (b1);
  1. 1 1 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  2. 1 2 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  3. 1 3 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  4. 一个都没找就返回空,最外层的NOT EXISTS就为真,输出
  5. 2 1 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  6. 2 2 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  7. 2 3 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  8. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  9. 3 1 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  10. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  11. 4 1 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  12. 4 2 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  13. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  14. 5 1 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  15. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出

2、查询至少选修了一门课程的学生

  1. SELECT name from t_student s where EXISTS (
  2. SELECT 1 from t_course c where EXISTS (
  3. SELECT 1 from t_student_course sc
  4. where sc.sid = s.id and sc.cid = c.id
  5. )
  6. )
  7. -- 赵子龙、关羽、张飞、黄忠
  1. 1 1 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  2. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  3. 2 1 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  4. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  5. 3 1 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  6. 3 2 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  7. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  8. 4 1 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  9. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  10. 5 1 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  11. 5 2 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  12. 5 3 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  13. 一个都没找就返回空,最外层的EXISTS就为假,不输出

3、查询没有选择所有课程的学生

  1. SELECT name from t_student s where EXISTS (
  2. SELECT 1 from t_course c where NOT EXISTS (
  3. SELECT 1 from t_student_course sc
  4. where sc.sid = s.id and sc.cid = c.id
  5. )
  6. )
  7. -- 关羽、张飞、黄忠、马超
  1. 1 1 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  2. 1 2 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  3. 1 3 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  4. 一个都没找就返回空,最外层的EXISTS就为假,不输出
  5. 2 1 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  6. 2 2 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  7. 2 3 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  8. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  9. 3 1 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  10. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  11. 4 1 遍历sc表找到一个匹配的立即返回真,最内层的NOT EXISTS就为假,b1为空,不能返回
  12. 4 2 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  13. 找到一个匹配的立即返回真,最外层的EXISTS就为真,输出
  14. 5 1 遍历sc表没有找到一个匹配的返回空(假),最内层的NOT EXISTS就为真,b1不为空,立即返回
  15. 找到一个匹配的立即返回真,最外层的EXISTS就为假,不输出

4、查询一门课也没有选的学生

  1. SELECT name FROM t_student s where NOT EXISTS (
  2. SELECT 1 from t_course c where EXISTS (
  3. SELECT 1 from t_student_course sc
  4. where sc.sid = s.id and sc.cid = c.id
  5. )
  6. )
  7. -- 马超
  1. 1 1 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  2. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  3. 2 1 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  4. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  5. 3 1 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  6. 3 2 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  7. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  8. 4 1 遍历sc表找到一个匹配的立即返回真,最内层的EXISTS就为真,b1不为空,立即返回
  9. 找到一个匹配的立即返回真,最外层的NOT EXISTS就为假,不输出
  10. 5 1 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  11. 5 2 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  12. 5 3 遍历sc表没有找到一个匹配的返回空,最内层的EXISTS就为假,b1为空,不能返回
  13. 一个都没找就返回空,最外层的NOT EXISTS就为真,输出

5、查询至少选修了学生2选修的全部课程的学生名单

  1. select * from t_student s where id != 2 and NOT EXISTS (
  2. select 1 from t_student_course sc where sid = 2 and NOT EXISTS (
  3. select 1 from t_student_course sc2
  4. where sc2.cid = sc.cid and sc2.sid = s.id
  5. )
  6. )
  7. -- 赵子龙

6、选出每门课程中成绩最高的学生

  1. SELECT * FROM t_student_course sc
  2. where sc.score = (SELECT max(score) FROM t_student_course sc2
  3. where sc2.cid = sc.cid)
  4. SELECT * FROM t_student_course sc where NOT EXISTS (
  5. SELECT 1 FROM t_student_course sc2
  6. where sc2.cid = sc.cid and sc2.score > sc.score
  7. )
  8. id sid cid score
  9. 3 1 3 100
  10. 4 1 4 97
  11. 7 2 2 100
  12. 8 2 3 100
  13. 9 3 1 100
  14. 11 4 5 100

最后来说说EXISTS、IN用法
EXISTS查询:先执行一次外部查询,然后为外部查询返回的每一行执行一次子查询,如果外部查询返回100行记录,sql就将执行101次查询。
IN查询:先查询子查询,然后把子查询的结果放到外部查询中进行查询。IN语句在mysql中没有参数个数的限制,但是mysql中sql语句有长度大小限制,整段最大为4M。IN引导的子查询只能返回一个字段。


EXISTS、IN怎么用
当子查询的表大的时候,使用EXISTS可以有效减少总的循环次数来提升速度,当外查询的表大的时候,使用IN可以有效减少对外查询表循环遍历来提升速度,
显然,外表大而子表小时,IN的效率更高,而外表小,子表大时,EXISTS的效率更高,若两表差不多大,则差不多。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/851862
推荐阅读
相关标签
  

闽ICP备14008679号