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

SQL 子查询全位置解析:可编写子查询的 7 大子句

🔍 SQL 子查询全位置解析:可编写子查询的 7 大子句

子查询可以出现在 SQL 语句的多个关键位置,不同位置的子查询具有独特的行为和限制。以下是系统化总结:


📌 1. WHERE 子句(最常用)

SELECTFROMWHERE 列 操作符 (SELECT ...);

类型

  • 标量子查询(单值)
  • 行子查询(单行多列)
  • 集合子查询(多行单列)
    示例
-- 标量子查询
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);-- 集合子查询
SELECT * FROM customers
WHERE id IN (SELECT cust_id FROM orders);

📊 2. FROM 子句(派生表)

SELECTFROM (SELECT ...) AS 别名 
WHERE 条件;

特点

  • 必须指定别名
  • 可包含任意复杂查询
  • 实质是创建临时视图
    示例
SELECT dept, avg_sal
FROM (SELECT dept_id, AVG(salary) AS avg_salFROM employeesGROUP BY dept_id
) AS dept_avg;

🎯 3. SELECT 子句(标量子查询)

SELECT,(SELECT ...) AS 别名 
FROM;

限制

  • 必须返回单行单列
  • 通常为关联子查询(引用外部列)
  • 每行都会执行一次
    示例
SELECT name,salary,(SELECT AVG(salary) FROM employees) AS avg_sal,salary - (SELECT AVG(salary) FROM employees) AS diff
FROM employees;

🔍 4. HAVING 子句

SELECT 聚合列 
FROMGROUP BYHAVING 聚合函数() 操作符 (SELECT ...);

特点

  • 在分组后执行
  • 可访问聚合函数结果
    示例
SELECT dept_id, AVG(salary) 
FROM employees
GROUP BY dept_id
HAVING AVG(salary) > (SELECT AVG(salary) FROM employees);

🔄 5. JOIN 子句

SELECTFROM1 
JOIN (SELECT ...) AS 别名 ON 连接条件;

优势

  • 预先过滤/聚合连接表
  • 减少连接数据量
    示例
SELECT c.name, o.order_count
FROM customers c
JOIN (SELECT cust_id, COUNT(*) AS order_countFROM ordersGROUP BY cust_id
) o ON c.id = o.cust_id;

⚙️ 6. INSERT 语句

插入数据来源
INSERT INTO 目标表 ()
SELECT ... FROM 源表;

示例

INSERT INTO premium_users (id, name)
SELECT id, name 
FROM users
WHERE total_spend > 10000;
插入值计算
INSERT INTO(1,2) 
VALUES ((SELECT ...), (SELECT ...)
);

限制

  • 每个子查询必须返回单值
    示例
INSERT INTO stats (total_users, avg_salary)
VALUES ((SELECT COUNT(*) FROM users),(SELECT AVG(salary) FROM employees)
);

✏️ 7. UPDATE 语句

UPDATESET= (SELECT ...) 
WHERE 条件;

关键点

  • SET 子句的子查询必须返回单值
  • WHERE 子句可嵌套子查询
    示例
-- 更新员工薪资为部门平均
UPDATE employees e
SET salary = (SELECT AVG(salary)FROM employees WHERE dept_id = e.dept_id
);

⚠️ 8. 特殊位置注意事项

ORDER BY 子句(少用)
SELECTFROMORDER BY (SELECT ...);

限制

  • 子查询必须返回单值
  • 每行执行一次,性能差
    示例
SELECT name, salary
FROM employees
ORDER BY (SELECT AVG(salary) FROM employees);
CREATE VIEW 语句
CREATE VIEW 视图名 AS
SELECT ... FROM (SELECT ...);

⚠️ 子查询通用注意事项

  1. NULL 处理

    • NOT IN 遇 NULL 返回空集 → 用 NOT EXISTS 替代
    -- 危险
    WHERE id NOT IN (SELECT ...) -- 安全
    WHERE NOT EXISTS (SELECT 1 FROM ...)
    
  2. 性能陷阱

    • 关联子查询(Correlated Subquery)导致 O(n²) 复杂度
    • 解决方案:
      -- 低效
      SELECT * FROM t1 
      WHERE col = (SELECT ... FROM t2 WHERE t2.id = t1.id)-- 高效:转为 JOIN
      SELECT t1.* 
      FROM t1 
      JOIN (SELECT ... FROM t2) sub ON t1.id = sub.id
      
  3. 返回结果限制

    位置允许的行/列是否需别名
    WHERE单行或多行(取决操作符)
    FROM任意
    SELECT单行单列可选
    HAVING单行或多行
    SET (UPDATE)单行单列
  4. 可读性优化

    • 超过 2 层嵌套时改用 CTE(公共表表达式):
    -- 嵌套子查询(难维护)
    SELECT ...
    FROM (SELECT ... FROM (SELECT ...)) -- CTE 优化版
    WITH step1 AS (SELECT ...),step2 AS (SELECT ... FROM step1)
    SELECT ... FROM step2;
    

💎 子查询位置决策指南

使用场景首选位置替代方案
行级条件过滤WHEREJOIN
创建临时数据集FROMCTE/临时表
动态计算列值SELECT应用层计算
分组后过滤HAVING子查询 + WHERE
批量插入数据INSERT SELECTETL工具
基于查询结果更新UPDATE SET多语句事务
复杂数据集连接前预处理JOIN物化视图

📌 黄金法则

  1. 能用 JOIN 解决不用子查询(优化器更易优化)
  2. 标量子查询优先放 SELECT,集合查询优先放 WHERE
  3. 关联子查询是 性能最后选项 - 必须用 EXPLAIN 分析
  4. MySQL 中避免在 SELECT 子查询更新相同表(错误 1093)

文章转载自:
http://acaudate.apjjykv.cn
http://aphtha.apjjykv.cn
http://arthroplastic.apjjykv.cn
http://cactus.apjjykv.cn
http://addible.apjjykv.cn
http://antibaryon.apjjykv.cn
http://aghan.apjjykv.cn
http://berascal.apjjykv.cn
http://audile.apjjykv.cn
http://bruin.apjjykv.cn
http://chastely.apjjykv.cn
http://chanel.apjjykv.cn
http://ammonic.apjjykv.cn
http://calaboose.apjjykv.cn
http://babs.apjjykv.cn
http://chlorine.apjjykv.cn
http://cartridge.apjjykv.cn
http://boffola.apjjykv.cn
http://catwalk.apjjykv.cn
http://ceroma.apjjykv.cn
http://auscultate.apjjykv.cn
http://acquittance.apjjykv.cn
http://bordeaux.apjjykv.cn
http://boatmanship.apjjykv.cn
http://chaetopod.apjjykv.cn
http://bulk.apjjykv.cn
http://belay.apjjykv.cn
http://blanquet.apjjykv.cn
http://cardiopathy.apjjykv.cn
http://baryonium.apjjykv.cn
http://www.dtcms.com/a/261456.html

相关文章:

  • Hyper-v-中的FnOs--飞牛Nas虚拟磁盘扩容(不清除数据)
  • Java安装与使用教程
  • 栅极驱动器选的好SiC MOSFET高效又安全
  • Gradio全解13——MCP详解(4)——TypeScript包命令:npm与npx
  • 【龙泽科技】新能源汽车故障诊断仿真教学软件【吉利几何G6】
  • SRS WebRTC 入门
  • 【数据标注师】分类标注
  • Push-T, AloHa, Rlbench三个仿真环境信息
  • 为何需要防爆平板?它究竟有何能耐?
  • 给定一个整型矩阵map,求最大的矩形区域为1的数量
  • Redis 高可用分片集群:主从模式与哨兵机制详解
  • 【AI智能体】Dify 核心组件从使用到实战操作详解
  • 33.表复制和去重
  • SpringMVC系列(五)(响应实验以及Restful架构风格(上))
  • maven多模块、多层级项目 如何只构建指定的项目
  • Web基础关键_004_CSS(二)
  • 在 CentOS Stream 10 上搭建 Kubernetes 集群并支持开发调试与日志查看
  • ZooKeeper深度面试指南一
  • React环境搭建及语法简介
  • PIC单片机MPLAB编译报错的一些问题及解决方法
  • python多线程详细讲解
  • Java-Matcher类
  • Grab×亚矩阵云手机:以“云端超级节点”重塑东南亚出行与数字生活生态
  • 【21】C9800配置PSK认证的WLAN
  • 【git教程】git add 命令讲解
  • 如何让ChatGPT模仿人类写作,降低AIGC率?
  • zookeeper Curator(2):Curator的节点操作
  • var let setTimeOut 经典面试题
  • 第十节:Vben Admin 最新 v5.0 (vben5) 快速入门 - 菜单管理(下)
  • 前端与 Spring Boot 后端无感 Token 刷新 - 从原理到全栈实践