当前位置: 首页 > ai >正文

SQL-子查询

SQL子查询是嵌套在另一个SQL查询中的SELECT语句,将内部查询的结果作为外部查询的条件或者数据源。

核心概念

子查询是一个完整的SELECT语句,可以嵌入到其他查询的where, from, SELECT, HAVING等子句中,用于动态生成条件或临时数据集。

例如

列出刘成所在系的全部同学的姓名

SELECTname
FROMstudent
WHEREdept = (SELECT dept FROM student WHERE name = '刘成')

分类

按返回结果集区分子查询

标量子查询

只返回单一值的子查询称之为标量子查询

例如
select * from t1 where m1 = (select min(m2) from t2)
select (select m1 from t1 limit 1)

行子查询

返回一条记录的子查询,这条记录包含多个列(只包含一个列就成了标量子查询)

比如SELECT * FROM t1 WHERE (m1, n1) = (SELECT m2, n2 FROM t2 LIMIT 1)

列子查询

查询出一个列的数据,这个列的数据包含多条记录

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

表子查询

子查询的结果包含很多条记录,又包含很多个列

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

按与外层查询关系区分子查询

相关子查询

子查询可以单独运行出结果,不依赖外层查询

不相关子查询

子查询的执行依赖于外层查询的值

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

子查询在布尔表示式中的使用

  • 使用=, >, <, >=, <=, <>, !=, <=>

子查询只能是标量子查询或者行子查询,也就是子查询的结果只能返回单一的值或者一条记录

标量子查询SELECT * FROM t1 WHERE m1 < (SELECT MIN(m2) FROM t2);

行子查询SELECT * FROM t1 WHERE (m1, n1) = (SELECT m2, n2 FROM t2 LIMIT 1)

  • [NOT] IN/ANY/SOME/ALL 子查询

对于列子查询和表子查询来说,他们的结果集中包含很多条记录,类似一个集合,就不能使用上面的操作符了。

  1. IN或者NOT IN

具体语法操作数 [NOT] IN (子查询)

判断某个操作数是否存在由子查询结果组成的集合中

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

  1. ANY/SOME(any和some是同义词)

具体语法操作数 操作符 ANY/SOME (子查询)

意思是:只要子查询的结果集合中有一条记录能满足比较的结果为真,则整个表达式的结果为真

SELECT * FROM t1 WHERE m1 > ANY(SELECT m2 FROM t2)

等价于SELECT * FROM t1 WHERE m1 > (SELECT MIN(m2) FROM t2);

  1. ALL

与ANY/SOME类似

SELECT * FROM t1 WHERE m1 > ALL(SELECT m2 FROM t2)

等价于SELECT * FROM t1 WHERE m1 > (SELECT MAX(m2) FROM t2)

  1. EXISTS子查询

有时候我们仅仅需要判断子查询的结果集中是否有记录,而不在乎他的记录具体是个啥,乐意使用EXISTS或者NOT EXISTS放在子查询语句的前边

[NOT] EXISTS (子查询)

比如SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2)

不关心子查询的结果是什么,只在乎子查询有没有记录

子查询注意事项

  • 子查询必须用小括号扩起来
  • SELECT子句中的子查询必须是标量子查询
  • 想要得到标量子查询或者行子查询,但又不能保证子查询的结果集只有一条记录时,应该使用LIMIT 1来限制记录数量
  • [NOT] IN/ANY/SOME/ALL子查询不允许子句中有LIMIT
  • 不允许增删改某个表同时还对该表进行子查询

原理

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

不相关子查询

SELECT * FROM s1 WHERE key1 = (SELECT common_field FROM s2 WHERE key3 = 'a' LIMIT 1

先单独执行(SELECT common_field FROM s2 WHERE key3 = 'a' LIMIT 1这个子查询,

然后将上一步子查询得到的结果当做外层查询的查询语句

也就是说,MySQL对于包含不相关的标量子查询或者行子查询的查询语句来说,MySQL会分别执行外层查询和子查询,就当做两个单表查询就好了

相关子查询

比如SELECT * FROM s1 WHERE key1 = (SELECT common_field FROM s2 WHERE s1.key3 = s3.key3 LIMIT 1)

先从外层查询中获取一条记录,本例中也就是s1表

然后执行子查询;如果满足子查询,则将记录添加到结果集,否则丢弃。

依次递推,知道遍历完外层表中的所有记录

IN子查询的优化

SELECT * FROM s1 WHERE key1 IN (SELECT common_field FROM s2 WHERE key3 = 'a')

物化表的提出

不相关子查询的结果集写入一个临时表

  • 该临时表的列就是子查询结果集中的列
  • 写入临时表的记录会被去重
  • 使用memory存储引擎的临时表,而且会为该表简历哈希索引

物化表转连接

从表1的角度看

从表2的角度看

总的来看,上面的含子查询的语句就转化成了

SELECT s1.* FROM s1 INNER JOIN materialized_table ON key1 = m_val

将子查询转换为semi-join

对于MySQL对外提供的接口不存在semi-join, 只是一种概念

不进行物化操作直接把子查询转化为连接

SELECT * FROM s1 WHERE key1 IN (SELECT common_field FROM s2 WHERE key3 = 'a')

类似于

SELECT s1.* FROM s1 INNER JOIN s2 ON s1.key1 = s2.common_field WHERE s2.key3 = 'a'

但是需要对结果去重,一个s1中的记录可以满足多条s2表中的记录

如何实现这种semi-join

  • table pullout(子查询中的表上拉)

当子查询的查询列表处只有主键或者唯一索引列时,可以直接把子查询中的上拉到外层查询的FROM子句中,并把子查询中的搜索条件合并到外层查询的搜索条件中

  • 重复值消除

执行连接查询时,消除重复的值。比如将结果集中的记录的主键插入到一个表中,插入失败丢弃该条记录

  • 首次匹配

先取一条外层查询的记录,如果能匹配到一条子查询中的记录,就直接返回

http://www.xdnf.cn/news/251.html

相关文章:

  • iPaaS应用集成平台在交通运输行业有哪些应用场景
  • (51单片机)LCD显示数据存储(DS1302时钟模块教学)(LCD1602教程)(独立按键教程)(延时函数教程)(I2C总线认识)(AT24C02认识)
  • 643SJBHflash个人网站
  • 【Python爬虫基础篇】--2.模块解析
  • AI时代的泛安全新范式:Kaamel安全智能体解决方案
  • 数据库被渗透怎么办?WAF能解决数据库安全问题吗?
  • 织梦DedeCMS首页列表页调用会员信息的SQL标签
  • 2025年人工智能指数报告(斯坦福)重点整理
  • 静态时序分析STA——8.2 时序检查(保持时间检查)
  • 第十四节:实战场景-何实现全局状态管理?
  • 【python】编码、输入、数据类型
  • CCF CSP 第36次(2024.12)(2_梦境巡查_C++)
  • 本地部署ai图片转生成视频,一键运行包的制作教程。
  • 调制器的噪声传递函数(NTF)的零极点配置对其性能的影响
  • L38.【LeetCode题解】四数之和(双指针思想) 从汇编角度分析报错原因
  • C++11中的std::condition_variable
  • 深度学习中的概念——元素积(哈达玛积)
  • Skipped breakpoint at ... because of stepping in another thread问题分析
  • 制造企业PLM深度应用:2025年基于PDCA循环的7项持续改进指标
  • 2025年Q2(桥式)起重机司机题库考试精选题
  • 高级java每日一道面试题-2025年4月13日-微服务篇[Nacos篇]-Nacos如何处理网络分区情况下的服务可用性问题?
  • AI的出现,是否能替代IT从业者?
  • 电子电器架构 --- OEM企标中规定ECU启动时间的目的
  • 第七篇:系统分析师第三遍——1、2章
  • 【Spring Boot】把jar包导入本地系统
  • C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息
  • 【前端HTML生成条形码——MQ】
  • DeepSeek深度观察:白宫“炒人“威胁的语义强度与市场应激量化分析
  • 【Unity】使用Cinemachine+CharacterController实现第三人称视角下的角色视角、移动和跳跃控制
  • Maven与Springboot创建