博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL基础-子查询&EXISTS&UNION
阅读量:5220 次
发布时间:2019-06-14

本文共 4380 字,大约阅读时间需要 14 分钟。

一、子查询

1、使用子查询作为计算字段

子查询:嵌套在其他查询中的查询现在有两个表,student表和teacher表创建teacher表,并插入数据:CREATE TABLE `teacher` (  `teacher_id` varchar(255) DEFAULT NULL COMMENT '老师编号',  `teacher_name` varchar(255) DEFAULT NULL COMMENT '老师姓名',  `gender` varchar(255) DEFAULT NULL COMMENT '性别') ENGINE=MyISAM DEFAULT CHARSET=gbk COMMENT='老师';INSERT INTO `teacher` VALUES ('T0001','高齐妍','男'),('T0002','李红','女'),('T0003','李一萱',NULL),('T0004','刘金霞','男'),('T0005','刘思哲','男'),('T0006','刘兆祥','男'),('T0007','刘哲宇','男'),('T0008','梅艺涵','女'),('T0009','梅姿君','女'),('T0010','牛雨','女'),('T0011','牛光滢','女'),('T0012','黄雅','女'),('T0013','任筱','女'),('T0014','吴静婷','男'),('T0015','习芸颍','女'),('T0016','叶惠燕','女'),('T0017','周纯','男'),('T0018','周圣杰','男'),('T0019','方焓','女'),('T0020','方杰萍','女');比如:    如何同时查询出学生编号、学生姓名、老师编号、老师姓名?    SELECT     student_id,    student_name,    teacher_id,    (        SELECT teacher_name        FROM teacher         -- 使用表名消除字段歧义        WHERE teacher.teacher_id = student.teacher_id    )    FROM student;    #可以为表指定别名    SELECT     student_id,    student_name,    teacher_id,    (        SELECT teacher_name        FROM teacher b        WHERE b.teacher_id = a.teacher_id    )    FROM student a;此时子查询不能返回多条记录;

2、使用子查询过滤数据(IN)

比如:    如何获取姓牛的老师教了哪些学生?    SELECT    student_id,student_name    FROM student    WHERE teacher_id IN ( SELECT teacher_id FROM teacher    WHERE teacher_name like '牛%');in 后面是一个集合;

3、IN和EXISTS比较

exists 与 in 最大的区别在于 in引导的子句只能返回一个字段;exists强调的是是否返回结果集,不要求知道返回什么;exists 是用来判断是否存在的,当exists(查询)中的查询存在结果时则返回真否则返回假。not exists则相反。EXISTS只返回TRUE或FALSE,不会返回UNKNOWN。IN当遇到包含NULL的情况,那么就会返回UNKNOWN。exists做为where条件时,是先对where前的主查询询进行查询,然后用主查询的结果一个一个的代入exists的查询进行判断,如果为真则输出当前这一条主查询的结果,否则不输出。select * from A where id in(select id from B)in()适合B表比A表数据小的情况;exists()适合B表比A表数据大的情况;当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用;

4、使用子查询过滤数据(EXISTS)

比如:    如何获取姓牛的老师教了哪些学生?    SELECT    student_id,student_name    FROM student a    -- 这里的select 1没有具体意义,写成select 2也可以;    WHERE EXISTS ( SELECT 1 FROM teacher b    WHERE a.teacher_id = b.teacher_id    AND b.teacher_name like '牛%'    );##NO EXISTS比如:    如何获取除姓牛的老师之外的其他老师教了哪些学生?    SELECT    student_id,student_name    FROM student a    WHERE NOT EXISTS ( SELECT 1 FROM teacher b    WHERE a.teacher_id = b.teacher_id    AND b.teacher_name like '牛%'    );

二、UNION

1、UNION 和UNION ALL

##比如:    如何同时查询出年龄为10岁或一年级一班的所有学生?    SELECT * FROM student WHERE age = 10    UNION ALL    SELECT * FROM student WHERE class_id = 'G0101';比如:    如何同时查询出年龄为10岁或一年级一班的所有学生(去除重复)?    SELECT * FROM student WHERE age = 10    UNION    SELECT * FROM student WHERE class_id = 'G0101';UNION ALL 与 UNION:    相同点:都是用来合并多个结果集;    不同点:UNION ALL合并结果集后不去除重复记录;          UNION合并结果集后去除重复记录;

2、合并2个以上的结果集

比如:    如何同时查询出年龄为10岁或一年级一班或性别为男的所有学生?    SELECT * FROM student WHERE age = 10    UNION    SELECT * FROM student WHERE class_id = 'G0101'    UNION    SELECT * FROM student WHERE gender = '男';

3、合并来源于不同的表的结果集

比如:    如何同时查询出所有的学生编号、学生姓名和老师编号、老师姓名?    SELECT student_id,student_name FROM student    UNION    SELECT teacher_id,teacher_name FROM teacher;

4、不同结果集什么情况下可以合并

需要注意:     待合并的结果集的字段数量必须一致。错误写法(字段数量不一致):            SELECT student_id,student_name,age FROM student    UNION    SELECT teacher_id,teacher_name FROM teacher;其他注意的几点:     合并后的结果集的title与第一个结果集保持一致。     待合并的结果集的字段顺序、字段类型的大类及字段值的含义尽量保持一致。如下,虽然不会报错,但是也应该尽量避免不一样的字段在同一列:    SELECT student_id,student_name,age FROM student    UNION    SELECT teacher_id,teacher_name,gender FROM teacher;以上注意事项,UNION和UNION ALL都适用;

5、UNION ALL与UNION混用

比如:    如何同时查询出年龄为10岁或一年级一班(前面两个结果集需要去除重复)或性别为男(合并时不去除重复)的所有学生?    SELECT * FROM student WHERE age = 10    UNION    SELECT * FROM student WHERE class_id = 'G0101'    UNION ALL    SELECT * FROM student WHERE gender = '男';需要注意的几点:     UNION ALL与UNION的执行优先级一致,谁在前谁先执行;     不可以使用括号改变执行优先级;不建议UNION ALL与UNION混用;

6、合并后的结果集排序

比如:    如何同时查询出年龄为10岁或一年级一班的所有学生(按姓名升序排序)?    SELECT * FROM student WHERE age = 10    UNION ALL    SELECT * FROM student WHERE class_id = 'G0101'    ORDER BY student_name;会先执行UNION ALL,再执行ORDER BY

7、union all&or&in的使用

union all 也不一定就比 or及in 快,要结合实际情况分析到底使用哪种情况。对于索引列来最好使用union all,因复杂的查询【包含运算等】将使or、in放弃索引而全表扫描,除非你能确定or、in会使用索引;对于只有非索引字段来说你就老老实实的用or 或者in,因为 非索引字段本来要全表扫描而union all 只成倍增加表扫描的次数;对于既有索引字段【索引字段有效】又包含非索引字段来时,按理你也使用or 、in或者union all 都可以,但是我推荐使用or、in。以上主要针对的是单表,而多表联合查询来说,考虑的地方就比较多了,比如连接方式,查询表数据量分布、索引等,再结合单表的策略选择合适的关键字;

转载于:https://www.cnblogs.com/weiyiming007/p/11433785.html

你可能感兴趣的文章
关于Matchvs一些使用心得与建议
查看>>
Gson获取json串中的key-value
查看>>
创建spring boot项目
查看>>
Behave + Selenium(Python) 四
查看>>
系统的横向结构(AOP)
查看>>
linux常用命令
查看>>
有序链表的归并 分类: 链表 2015-06-...
查看>>
A Plug for UNIX 分类: POJ ...
查看>>
寒假作业01
查看>>
自定义simple_tag
查看>>
ubuntu配置全局环境变量后开新shell变量无效的解决方法
查看>>
表格只要外面的边框,不要里面的横线
查看>>
文件名&关键字&标识符、变量声明、流程控制语句
查看>>
第二章002 定位元素
查看>>
MyBatis缓存
查看>>
STL 练习
查看>>
Java开发笔记(八)五种算术运算符
查看>>
spring加载hibernate映射文件的几种方式。转自:http://blog.csdn.net/huiwenjie168/article/details/7013618...
查看>>
C#保存登录用户名供其他页面调用
查看>>
DP专题训练之HDU 1864 最大报销额
查看>>