Mysql——子查询
select 中、from 后、where 中.group by 和order by 中无实用意义。
子查询分为如下几类:
1,标量子查询:返回单一值的标量,最简单的形式。
2,列子查询:返回的结果集是 N 行一列。
3,行子查询:返回的结果集是一行 N 列。
4,表子查询:返回的结果集是 N 行 N 列。
可以使用的操作符:= > < >= <= <> ANY IN SOME ALL EXISTS
标量子查询:是指子查询返回的是单一值的标量,如一个数字或一个字符串,也是子查询中最简单的返回形式。
可以使用 = > < >= <= <> 这些操作符对子查询的标量结果进行比较,通常子查询的位置在比较式的右侧
示例:
SELECT * FROM article WHERE uid = (SELECT uid FROM user WHERE status=1 ORDER BY uid DESC LIMIT 1)
SELECT * FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2)
SELECT * FROM article AS t WHERE 2 = (SELECT COUNT(*) FROM article WHERE article.uid = t.uid)
MySQL 列子查询:指子查询返回的结果集是 N 行一列,该结果通常来自对表的某个字段查询返回。
可以使用 = > < >= <= <> 这些操作符对子查询的标量结果进行比较,通常子查询的位置在比较式的右侧
示例:可以使用 IN、ANY、SOME 和 ALL 操作符,不能直接使用 = > < >= <= <> 这些比较标量结果的操作符。
示例:
SELECT * FROM article WHERE uid IN(SELECT uid FROM user WHERE status=1)
SELECT s1 FROM table1 WHERE s1 > ANY (SELECT s2 FROM table2)
SELECT s1 FROM table1 WHERE s1 > ALL (SELECT s2 FROM table2)
NOT IN 是 <> ALL 的别名,二者相同。
特殊情况
如果 table2 为空表,则 ALL 后的结果为 TRUE;
如果子查询返回如 (0,NULL,1) 这种尽管 s1 比返回结果都大,但有空行的结果,则 ALL 后的结果为 UNKNOWN 。
注意:对于 table2 空表的情况,下面的语句均返回 NULL:
SELECT s1 FROM table1 WHERE s1 > (SELECT s2 FROM table2)
SELECT s1 FROM table1 WHERE s1 > ALL (SELECT MAX(s1) FROM table2)
MySQL 行子查询:指子查询返回的结果集是一行 N 列,该子查询的结果通常是对表的某行数据进行查询而返回的结果集。
例子:
SELECT * FROM table1 WHERE (1,2) = (SELECT column1, column2 FROM table2)
注:(1,2) 等同于 row(1,2)
SELECT * FROM article WHERE (title,content,uid) = (SELECT title,content,uid FROM blog WHERE bid=2)
MySQL 表子查询:指子查询返回的结果集是 N 行 N 列的一个表数据。
例子:
SELECT * FROM article WHERE (title,content,uid) IN (SELECT title,content,uid FROM blog)
子查询优化:
很多查询中需要使用子查询。使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死。子查询可以使查询语句很灵活,但子查询的执行效率不高。子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句再临时表中查询记录。查询完毕后,MySQL需要撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。在MySQL中可以使用连接查询来替代子查询。连接查询不需要建立临时表,其速度比子查询要快。
使用连接(JOIN)来代替子查询
如:
例子1:
SELECT * FROM t1
WHERE t1.a1 NOT in (SELECT a2 FROM t2 )
优化后:
SELECT * FROM t1
LEFT JOIN t2 ON t1.a1=t2.a2
WHERE t2.a2 IS NULL
例子2:
SELECT * FROM article WHERE (title,content,uid) IN (SELECT title,content,uid FROM blog)
优化后:
SELECT * FROM article
inner join blog
on (article.title=blog.title AND article.content=blog.content AND article.uid=blog.uid)
不能优化的子查询:
1、mysql不支持子查询合并和聚合函数子查询优化,mariadb对聚合函数子查询进行物化优化;
2、mysql不支持from子句子查询优化,mariadb对from子句子查询进行子查询上拉优化;
3、mysql和mariadb对子查询展开提供有限的支持,如对主键的操作才能进行上拉子查询优化;
4、mysql不支持exists子查询优化,mariadb对exists关联子查询进行半连接优化,对exists非关联子查询没有进一步进行优化;
5、mysql和mariadb不支持not exists子查询优化;
6、mysql和mariadb对in子查询,对满足半连接语义的查询进行半连接优化,再基于代价评估进行优化,两者对半连接的代价评估选择方式有差异;
7、mysql不支持not in子查询优化,mariadb对非关联not in子查询使用物化优化,对关联not in子查询不做优化;
8、mysql和mariadb对>all非关联子查询使用max函数,<all非关联子查询使用min函数,对=all和非关联子查询使用exists优化;
9、对>some和>any非关联子查询使用min函数,对<some和<any非关联子查询使用max函数,=any和=some子查询使用半连接进行优化,对>some和>any关联子查询以及<some和<any关联子查询只有exists优化。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。