SQL子查询实战:相关子查询vs非相关子查询,用法解析
前言
子查询是SQL进阶的核心,简单说就是SQL中嵌套SQL。日常开发中,复杂筛选、批量匹配、嵌套统计都需要用到子查询。
很多新手只会写简单子查询,分不清相关子查询和非相关子查询的区别,不知道什么时候用哪种,导致代码冗余、性能低下。
一、子查询基础概念
外层SQL:父查询;括号内嵌套的SQL:子查询。
分类核心依据:子查询是否依赖父查询的字段。
不依赖 = 非相关子查询(独立执行);依赖 = 相关子查询(逐行执行)。
二、非相关子查询(独立子查询)
核心特点
子查询完全独立,不引用父查询的任何字段,只会执行一次,执行效率高。
常用场景
固定条件筛选、批量匹配、获取统计值、IN / EXISTS 固定值匹配。
实战案例
-- 案例:查询有订单的所有用户(非相关子查询) SELECT * FROM user WHERE id IN (SELECT DISTINCT user_id FROM `order`);解析:子查询单独执行,查询出所有有订单的用户ID,再给父查询筛选,子查询只执行1次。
三、相关子查询(关联子查询)
核心特点
子查询依赖父查询字段,无法独立运行,会随着父查询的每一行数据逐行循环执行,数据量大时性能较差。
常用场景
逐行匹配统计、单行数据校验、复杂行级筛选。
实战案例
-- 案例:查询每个用户的订单数量大于0的用户 SELECT * FROM user u WHERE EXISTS ( SELECT 1 FROM `order` o WHERE o.user_id = u.id );解析:子查询引用了父查询的 u.id 字段,依赖父查询,父查询每遍历一行,子查询执行一次。
四、两种子查询核心区别对比
对比维度 | 非相关子查询 | 相关子查询 |
|---|---|---|
执行依赖 | 独立执行,不依赖父查询 | 依赖父查询字段,无法独立运行 |
执行次数 | 仅执行1次 | 父查询多少行,执行多少次 |
执行性能 | 高,推荐优先使用 | 低,大数据量慎用 |
五、子查询开发规范与优化
1、优先使用非相关子查询,尽量避免循环执行的相关子查询;
2、大数据量场景,相关子查询可改写为 LEFT JOIN 关联查询,大幅提升性能;
3、子查询尽量返回固定字段,禁止 SELECT *,减少数据传输开销。
