子查询是嵌套在另一个查询中的
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 e1WHERE 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 对子查询施加了以下限制:
运算符限制:标量子查询不能与
ANY、ALL 或 SOME 运算符一起使用。比较限制:对于
EXISTS 子句,外层与内层之间的比较必须包含至少一次相等比较。上下文限制:
标量子查询仅支持数值上下文。不能用于
LIKE、REGEXP 或与 TIMESTAMP 等非数值类型的比较。不能在
CASE 表达式中作为比较值或返回值。不能用作
BETWEEN 运算符的参数。逻辑连接限制:子查询不能出现在
OR 连接条件的外部(即 WHERE (subquery) OR col = 1 是不允许的)。引用限制:在子查询中引用外层列时,必须使用完全限定名。