当前位置:   article > 正文

MySQL子查询原理分析

mysql子查询原理

01

前言

子查询,通俗解释就是查询语句中嵌套着另一个查询语句。相信日常工作中接触到 MySQL 的同学都了解或使用过子查询,但是具体它是怎样实现的呢? 查询效率如何? 这些恐怕好多人就不太清楚了,下面咱们就围绕这两个问题共同探索一下。

02

准备内容

这里我们需要用到3个表,这3个表都有一个主键索引 id 和一个索引 a,字段 b 上无索引。存储过程 idata() 往表 t1 里插入的是 100 行数据,表 t2、t3 里插入了 1000 行数据。建表语句如下:

  1. CREATE TABLE `t1` (
  2. `id` INT ( 11 ) NOT NULL,
  3. `t1_a` INT ( 11 ) DEFAULT NULL,
  4. `t1_b` INT ( 11 ) DEFAULT NULL,
  5. PRIMARY KEY ( `id` ),
  6. KEY `idx_a` ( `t1_a` )) ENGINE = INNODB;
  7. CREATE TABLE `t2` (
  8. `id` INT ( 11 ) NOT NULL,
  9. `t2_a` INT ( 11 ) DEFAULT NULL,
  10. `t2_b` INT ( 11 ) DEFAULT NULL,
  11. PRIMARY KEY ( `id` ),
  12. KEY `idx_a` ( `t2_a` )) ENGINE = INNODB;
  13. CREATE TABLE `t3` (
  14. `id` INT ( 11 ) NOT NULL,
  15. `t3_a` INT ( 11 ) DEFAULT NULL,
  16. `t3_b` INT ( 11 ) DEFAULT NULL,
  17. PRIMARY KEY ( `id` ),
  18. KEY `idx_a` ( `t3_a` )) ENGINE = INNODB;
  19. -- 向t1添加100条数据
  20. -- drop procedure idata;
  21. delimiter ;;
  22. create procedure idata()
  23. begin
  24. declare i int;
  25. set i=1;
  26. while(i<=100)do
  27. insert into t1 values(i, i, i);
  28. set i=i+1;
  29. end while;
  30. end;;
  31. delimiter ;
  32. call idata();
  33. -- 向t2添加1000条数据
  34. drop procedure idata;
  35. delimiter ;;
  36. create procedure idata()
  37. begin
  38. declare i int;
  39. set i=101;
  40. while(i<=1100)do
  41. insert into t2 values(i, i, i);
  42. set i=i+1;
  43. end while;
  44. end;;
  45. delimiter ;
  46. call idata();
  47. -- 向t2添加1000条数据,且t3_a列的值为倒叙
  48. drop procedure idata;
  49. delimiter ;;
  50. create procedure idata()
  51. begin
  52. declare i int;
  53. set i=101;
  54. while(i<=1100)do
  55. insert into t3 values(i, 1101-i, i);
  56. set i=i+1;
  57. end while;
  58. end;;
  59. delimiter ;
  60. call idata();

03

子查询的语法形式和分类

3.1 语法形式

子查询的语法规定,子查询可以在一个外层查询的各种位置出现,这里我们只介绍常用的几个:

3.1.1  FROM子句中

如 SELECT m, n FROM (SELECT m2 + 1 AS m, n2 AS n FROM t2 WHERE m2 > 2) AS t;

这个例子中的子查询是:(SELECT m2 + 1 AS m, n2 AS n FROM t2 WHERE m2 > 2),这个放在FROM子句中的子查询相当于一个表,但又和我们平常使用的表有点儿不一样,这种由子查询结果集组成的表称之为派生表。

3.1.2 WHERE或IN子句中

如:SELECT * FROM t1 WHERE m1 = (SELECT MIN(m2) FROM t2);

       SELECT * FROM t1 WHERE m1 IN (SELECT m2 FROM t2);

其他的还有 SELECT 子句中,ORDER BY 子句中,GROUP BY 子句中,虽然语法支持,但没啥意义,就不唠叨这些情况了。

3.2 分类

3.2.1 按返回的结果集区分
  1. 标量子查询,只返回一个单一值的子查询称之为标量子查询,比如:

    SELECT * FROM t1 WHERE m1 = (SELECT m1 FROM t1 LIMIT 1);

  2. 行子查询,就是只返回一条记录的子查询,不过这条记录需要包含多个列(只包含一个列就成了标量子查询了)。比如:SELECT * FROM t1 WHERE (m1, n1) = (SELECT m2, n2 FROM t2 LIMIT 1);

  3. 列子查询,就是只返回一个列的数据,不过这个列的数据需要包含多条记录(只包含一条记录就成了标量子查询了)。比如:SELECT * FROM t1 WHERE m1 IN (SELECT m2 FROM t2);

  4. 表子查询,就是子查询的结果既包含很多条记录,又包含很多个列,比如:

    SELECT * FROM t1 WHERE (m1, n1) IN (SELECT m2, n2 FROM t2);

    其中的 (SELECT m2, n2 FROM t2) 就是一个表子查询,这里需要和行子查询对比一下,行子查询中我们用了 LIMIT 1 来保证子查询的结果只有一条记录。

3.2.2 按与外层查询关系来区分

不相关子查询,就是子查询可以单独运行出结果,而不依赖于外层查询的值,我们就可以把这个子查询称之为不相关子查询。

相关子查询,就是需要依赖于外层查询的值的子查询称之为相关子查询。比如:SELECT * FROM t1 WHERE m1 IN (SELECT m2 FROM t2 WHERE n1 = n2);

04

子查询在MySQL中是怎么执行的

4.1 标量子查询、行子查询的执行方式

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

闽ICP备14008679号