问题的历史:
嵌套子查询最初在SQL中设计用于扩展语言的表达能力,并解决不适合简单SELECT操作的复杂商业问题。然而,随着数据量的增长和关系模型的复杂性,逐渐认识到并非所有情况下嵌套子查询都是高效的:这在很大程度上取决于特定数据库管理系统的优化器的实现。
问题:
主要挑战是找到可读性、逻辑正确性和性能之间的平衡。嵌套子查询并不总是被优化为JOIN操作,通常会变成代价高昂的循环遍历(Nested Loops)。
解决方案:
代码示例:
-- 在SELECT中使用嵌套子查询(需谨慎!) SELECT name, (SELECT COUNT(*) FROM orders WHERE orders.client_id = clients.id) AS order_count FROM clients; -- 通过JOIN的等价形式(通常更快): SELECT clients.name, COUNT(orders.id) AS order_count FROM clients LEFT JOIN orders ON orders.client_id = clients.id GROUP BY clients.name;
关键特点:
嵌套子查询在SELECT中是否比相应的LEFT JOIN执行得更快?
通常不是。SELECT中的相关子查询为外部查询的每一行执行,而JOIN则为整个表构建一次索引。
可以在FROM中使用子查询代替CTE(WITH),会有区别吗?
可以,用在FROM中的子查询:
SELECT t1.id, sub.agg FROM table1 t1 JOIN (SELECT id, MAX(val) AS agg FROM table2 GROUP BY id) sub ON t1.id = sub.id;
但CTE有时可读性更强,可能在执行计划中导致不同的优化。
所有嵌套子查询都能优化为相应的JOIN吗?
不,并非所有数据库都能做到这一点,有时嵌套子查询会导致每一行被扫描,特别是当外部查询和内部查询之间有相关性时。
销售经理做了一个客户报告,内部SELECT算订单数量。执行时间 — 几分钟,服务器负载呈几何级数增长。
优点:
查询重写为使用LEFT JOIN和分组。
优点: