SQL 入门 9:SQL 高级子查询:ANY、EXISTS 与多位置应用

以下为 SQL 中高级子查询的用法解析,涵盖 ANY、EXISTS 及子查询的多位置应用。

学习内容

  1. ANY 关键字
  • 与子查询结果集的任一值比较,等效于 IN(用于相等时)。
  • 返回多值时使用。
  • 相关子查询

    • 子查询依赖外部查询的列,逐行执行。
    • 示例:比较员工薪资与其部门平均值。
  • EXISTS

    • EXISTS:逐行检查,子查询结果集大时性能较优。
    • IN:先执行子查询,外部表大时更快。
    • 连接:需根据需求选择(如 LEFT JOIN 加 IS NULL)。
    • 判断子查询是否有记录返回,适用于相关子查询。
    • 与 IN 和连接对比:
  • SELECT 中的子查询

    • 在列中嵌入子查询,计算动态值。
    • 限制:同一级别查询不能直接引用新列名,需通过外层查询或后续语句(如 ORDER BY、HAVING)使用。
  • FROM 中的子查询

    • 将子查询结果作为虚拟表,需指定别名。
    • 可用于复杂数据处理,类似临时表。

    示例代码与讲解

    1. ANY 关键字

    SELECT *

    FROM clients

    WHERE client_id IN (

    SELECT client_id

    FROM invoices

    GROUP BY client_id

    HAVING COUNT(*) > 2

    );

    • 找出发票数 > 2 的客户。

    SELECT *

    FROM clients

    WHERE client_id = ANY (

    SELECT client_id

    FROM invoices

    GROUP BY client_id

    HAVING COUNT(*) > 2

    );

    • 用 ANY 替代 IN,效果相同,表示匹配子查询任一值。

    2. 相关子查询

    USE sql_hr;

    SELECT *

    FROM employees e

    WHERE salary > (

    SELECT AVG(salary)

    FROM employees e2

    WHERE e2.office_id = e.office_id

    );

    • 找出薪资高于所在办公室平均值的员工,子查询与外部 office_id 相关。

    3. EXISTS

    USE sql_invoicing;

    SELECT client_id, name

    FROM clients c

    WHERE EXISTS (

    SELECT client_id

    FROM invoices ci

    WHERE c.client_id = ci.client_id

    );

    • 找出有发票的客户,逐行检查是否存在匹配记录。

    4. SELECT 中的子查询

    SELECT invoice_id, invoice_total,

    (SELECT AVG(invoice_total) FROM invoices) AS avginvoice_total,

    (SELECT avginvoice_total) - invoice_total AS difference

    FROM invoices;

    • 计算每张发票与平均值的差额。
    • 注意:avginvoice_total 不能直接在同级使用,需通过外层查询引用。

    5. FROM 中的子查询

    SELECT *

    FROM (

    SELECT c.client_id, name,

    (SELECT SUM(i.invoice_total) FROM invoices i WHERE c.client_id = i.client_id) AS total_sales,

    (SELECT AVG(invoice_total) FROM invoices) AS AVERAGE,

    (SELECT total_sales - AVERAGE) AS difference

    FROM clients c

    ) AS SUMMARY

    WHERE total_sales IS NOT NULL;

    • 将子查询结果作为虚拟表 SUMMARY,筛选非空销售总额。

    作业

    1. 相关子查询

    USE sql_invoicing;

    SELECT *

    FROM invoices i

    WHERE invoice_total > (

    SELECT AVG(invoice_total)

    FROM invoices i2

    WHERE i.client_id = i2.client_id

    );

    • 找出总额高于其客户平均值的发票。

    2. EXISTS

    USE sql_store;

    SELECT *

    FROM products p

    WHERE NOT EXISTS (

    SELECT *

    FROM order_items

    WHERE p.product_id = order_items.product_id

    );

    • 找出从未被订购的产品。

    3. SELECT 中的子查询

    USE sql_invoicing;

    CLEARSELECT c.client_id, name,

    (SELECT SUM(i.invoice_total) FROM invoices i WHERE c.client_id = i.client_id) AS total_sales,

    (SELECT AVG(invoice_total) FROM invoices) AS AVERAGE,

    (SELECT total_sales - AVERAGE) AS difference

    FROM clients c;

    • 计算每个客户的销售总额、平均值及差额,避免 GROUP BY。

    总结

    本次解析了 ANY(等效 IN)、相关子查询、EXISTS 及子查询在 SELECT 和 FROM 中的应用。基于 sql_invoicing、sql_hr 和 sql_store 数据库。后续将探讨视图与事务。

相关推荐
YOU OU1 小时前
Redis基础常识与命令
数据库·redis·缓存
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔1 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
Database_Cool_3 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
爱写代码的阿森4 小时前
鸿蒙三方库 | harmony-utils之KvUtil键值型数据库操作详解
数据库·华为·harmonyos·鸿蒙·huawei
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
Database_Cool_4 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql