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 数据库。后续将探讨视图与事务。

相关推荐
数据技术说11 分钟前
MySQL 迁移实战——如何实现真正的"零改造"平滑切换
mysql
MacroZheng22 分钟前
短短几天,暴涨2.8万Star!又一款编程神器开源!
java·人工智能·后端
SamDeepThinking35 分钟前
函数式编程:用BiFunction消除多类型分支的代码重复
java·后端·面试
倔强的石头_15 小时前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库
SelectDB17 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
Flittly18 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了18 小时前
Java 生成二维码解决方案
java·后端
人活一口气1 天前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP1 天前
Vibe Coding -- 完整项目案例实操
java
荣码1 天前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python