关于mysql中select子查询
来源:互联网 发布:南京行知小学宿舍 编辑:程序博客网 时间:2024/06/06 14:28
今天要分享的内容是mysql的select子查询
一直记得凯哥,半年前说过的一句话,原来你不知道,子查询啊,其实,我知道是又这么一回事
但是,具体又说不上来,大概就是那种,一看就知道,但是你有不完全知道的类型吧
现在在写hive语法的时候又碰到了,那么就好好总结一次吧。
子查询定义
在一个表表达中可以调用另一个表表达式,这个被调用的表表达式叫做子查询(subquery),
那么也称作子选择(subselect)或内嵌选择(inner select)。
子查询的结果传递给调用它的表达式继续处理。
说人话就是,一个sql语句,出现了2个以上的select关键词,这个清晰了吧?
子查询分类1
1*1 标量子查询:返回的结果集是一个标量集合,一行一列,也就是一个标量值。可以指定一个标量表达式的任何地方,都可以用一个标量子查询。1*n 行子查询:返回的结果集是一个列的集合,一行N列(N>=1)。行子查询可以用于福查询的FROM子句和WHERE子句中。n*1 列子查询:返回的结果集是一个行的集合,N行一列(N>=1)。n*n 表子查询:返回的结果集是一个行的集合,N行N列(N>=1)。表子查询经常用于父查询的FROM子句中。 就这么四类
从定义上讲,
每个标量子查询也是一个行子查询和一个列子查询,反之则不是;
每个行子查询和列子查询也是一个表子查询,反之也不是。
子查询分类2
where型子查询:(把内层查询结果当作外层查询的比较条件)定义:where型的子查询就是把内层查询的结果当作外层查询的条件。from型子查询:(把内层的查询结果供外层再次查询)定义:from子查询就是把子查询的结果(内存里的一张表)当作一张临时表,然后再对它进行处理。exists型子查询:(把外层查询结果拿到内层,看内层的查询是否成立)定义:exists子查询就是对外层表进行循环,再对内表进行内层查询。和in ()差不多,但是它们还是有区别的。主要是看两个张表大小差的程度。若子查询表大则用exists(内层索引),子查询表小则用in(外层索引);
其实,光这么说,很难明白的,因为你都没写过,根本理解不了,尤其是exisit子查询
使用子查询原则
1.一个子查询必须放在圆括号中。 2.将子查询放在比较条件的右边以增加可读性。 子查询不包含 ORDER BY 子句。对一个 SELECT 语句只能用一个 ORDER BY 子句,并且如果指定了它就必须放在主 SELECT 语句的最后。 3.在子查询中可以使用两种比较条件:单行运算符(>, =, >=, <, <>, <=) 和多行运算符(IN, ANY, ALL)。
where型子查询
select * from a where a.xx = (select xx from b where b.xx=”xx”),这种感觉
from型子查询
select * from (select * from a) as aa,这种感觉
exists型子查询
因为上面那两种,子查询,很明了简单,就不谈了,主要说下面的
尽量表达清楚
EXISTS关键字表示存在。使用EXISTS关键字时,内层查询语句不返回查询的记录,而是返回一个真假值,如果内层查询语句查询到满足条件的记录,只要子查询中至少返回一个值,则EXISTS语句的值就为True。就返回true,否则返回false。当返回的值为true时,外层查询语句将进行查询,否则不进行查询。NOT EXISTS刚好与之相反。exists的用法和in ()差不多,但是它们还是有区别的。主要是看两个张表大小差的程度。若子查询表大则用exists(内层索引),子查询表小则用in(外层索引);
看上面这段话的,解释,保证,你看了,也不知道在说啥,其实说的稍微有点问题
正确的解释,应该是,上面的当然也没错
exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当 exists里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录,反之如果exists里的条 件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为 false
就是循环外层的查询结果,然后带进去,查看条件是否成立,不成立丢弃,成立留下
select * from user where exists (select 1);这句话,就会输出,user表中全部的人,因为后面的条件,对于每个人都成立
select * from user where userId in (1, 2, 3);
这样的in查询,等价于
select * from user where userId = 1 or userId = 2 or userId = 3;
因此,要求in后面的表是小表,才不至于,很大的表,循环多次
记住一句话,谁的表大就用谁的索引
下面来考虑exists和in的性能
考虑如下SQL语句1: select * from A where exists (select * from B where B.id = A.id);2: select * from A where A.id in (select id from B);
查询1.可以转化以下伪代码,便于理解
for ($i = 0; $i < count(A); $i++) { $a = get_record(A, $i); #从A表逐条获取记录 if (B.id = $a[id]) #如果子条件成立 $result[] = $a; }return $result;
大概就是这么个意思,其实可以看到,查询1主要是用到了B表的索引,A表如何对查询的效率影响应该不大
也就是说,表B越大就越能利用到索引的优势
而假设B表是小表的所有id为1,2,3,查询2可以转换为
select * from A where A.id = 1 or A.id = 2 or A.id = 3;
这个好理解了,这里主要是用到了A的索引,B表如何对查询影响不大
也就是说,表A越大就越能利用到索引的优势
下面再看not exists 和 not in
1. select * from A where not exists (select * from B where B.id = A.id);2. select * from A where A.id not in (select id from B);
看查询1,还是和上面一样,用了B的索引
而对于查询2,可以转化成如下语句
select * from A where A.id != 1 and A.id != 2 and A.id != 3;
可以知道not in是个范围查询,这种!=的范围查询无法使用任何索引,等于说A表的每条记录,都要在B表里遍历一次,查看B表里是否存在这条记录
not in 和not exists如果查询语句
使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。
所以无论那个表大,用not exists都比not in要快。
总结
先大概说一下,这个子查询吧,其实,mysql还有很多的细节地方要注意,有时间再说说,自己的理解吧
补充一句,昨天和妹子出去吃饭,今天居然就感冒生病了,心疼啊/(ㄒoㄒ)/~~,怪我了
- 关于mysql中select子查询
- 关于mysql 子查询中 使用 limit
- MySQL在字段中使用select子查询
- MySQL在字段中使用select子查询
- MySQL在字段中使用select子查询
- MySQL在字段中使用select子查询
- mysql查询语句select-子查询
- 在 SELECT 查询中使用子查询
- MySQL如何将select子查询结果横向拼接后插入数据表中
- mysql学习-select查询,子查询,联…
- mysql中链接子查询
- mysql中exists子查询
- Mysql子查询-select语句嵌套-检索多个表
- mysql 数据库学习笔记 3 外键 和 select 子查询
- MySQL select 子查询复用,进行聚合计算
- MySQL中select查询的使用
- 【mysql】关于子查询的一个例子
- mysql关于视图、子查询、事物
- 决策树(decision tree)简介
- 如何完美的解释reducebyKey
- 轻轻松松来了解WIFI
- 《剑指Offer》第二章
- 我的第一个hbuilder项目
- 关于mysql中select子查询
- MySQL 查询某字段的多条结果展示成按逗号隔开
- 百度前端面试
- ssh 配置互信失败可能遇到的问题。
- codevs 1048 合并石子
- 图像旋转后的还原图像坐标
- 我的第一个五子棋游戏
- 日期计算器
- oracle循环执行sql