子查询

最近更新时间:2026-05-06 16:28:13

我的收藏
子查询是嵌套在另一个查询中的 SELECT 语句。它允许查询逻辑根据另一个表的内容动态调整,为 SQL 提供了强大的表达能力和灵活性。

子查询分类

标量子查询 (Scalar Subqueries)

定义:返回结果仅为 单行单列 的子查询。
特性:常用于聚合计算(如 MAX())。该单一值可以替换到任何需要标量值的上下文中(如比较运算符)。
空值处理:如果子查询未匹配到任何行,结果视为 NULL
示例:SELECT x FROM t1 WHERE x > (SELECT MAX(y) FROM t2);

非关联子查询 (Non-Correlated Subqueries)

定义:子查询内部不引用外层查询的任何表。
执行逻辑:子查询仅计算一次,其结果集作为常量提供给外层查询遍历使用。
示例:SELECT x FROM t1 WHERE x IN (SELECT y FROM t2);

关联子查询 (Correlated Subqueries)

定义:子查询内部引用了外层查询的列。
执行逻辑:外层查询的每一行都会驱动子查询重新计算,具有极强的动态过滤能力。
示例:
-- 查找工资高于所在部门平均水平的员工
SELECT name FROM employees e1
WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e1.dept_id = e2.dept_id);

语法与位置

SELECT select_list FROM table_ref [, table_ref ...]

table_ref ::= table_name | (select_statement)
子查询可以出现在以下位置:
1. FROM 子句:作为“派生表”或“内联视图”。
2. WHERE 子句:配合比较运算符(=>)、[NOT] IN[NOT] EXISTS
3. HAVING 子句:用于过滤聚合后的组数据。

开发建议与调优

表别名引用:如果内层和外层引用了同一张表,必须使用别名来区分列的作用域。
SELECT * FROM t1 `one` WHERE id IN (SELECT parent FROM t1 `two` WHERE `one`.parent = `two`.id);
连接顺序控制:STRAIGHT_JOIN 提示仅作用于其所在的当前查询块。如果需要优化嵌套视图或子查询的连接顺序,需在对应的嵌套块内分别添加提示。
性能权衡:关联子查询虽然功能强大,但在处理大数据量时可能会导致频繁的子查询评估。在性能敏感场景下,优先考虑将其重写为 JOIN 形式。

限制

为保证分布式执行的稳定性,TCHouse-X 对子查询施加了以下限制:
运算符限制:标量子查询不能与 ANYALLSOME 运算符一起使用。
比较限制:对于 EXISTS 子句,外层与内层之间的比较必须包含至少一次相等比较。
上下文限制:
标量子查询仅支持数值上下文。不能用于 LIKEREGEXP 或与 TIMESTAMP 等非数值类型的比较。
不能在 CASE 表达式中作为比较值或返回值。
不能用作 BETWEEN 运算符的参数。
逻辑连接限制:子查询不能出现在 OR 连接条件的外部(即 WHERE (subquery) OR col = 1 是不允许的)。
引用限制:在子查询中引用外层列时,必须使用完全限定名。