子查询(Subqueries)
子查询(subquery,也称内层查询或嵌套查询)是查询中的
查询。
子查询可以用于 SELECT、FROM、WHERE 和 HAVING 子句。
以下示例基于下面两张表。
SELECT * FROM x;
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 1 | 2 |
+----------+----------+
| 2 | 4 |
+----------+----------+
SELECT * FROM y;
+--------+--------+
| number | string |
+--------+--------+
| 1 | one |
+--------+--------+
| 2 | two |
+--------+--------+
| 3 | three |
+--------+--------+
| 4 | four |
+--------+--------+
子查询运算符(Subquery Operators)
[ NOT ] EXISTS
EXISTS 运算符返回所有满足以下条件的行:相关子查询
(correlated subquery)对该行产生一个或多个匹配。NOT EXISTS 返回 相关子查询
对该行产生零个匹配的所有行。仅支持 相关子查询。
[NOT] EXISTS (subquery)
[ NOT ] IN
IN 运算符返回所有满足以下条件的行:给定表达式的值能在
相关子查询 的结果中找到。
NOT IN 返回给定表达式的值在子查询结果或值列表中找不到的所有行。
expression [NOT] IN (subquery|list-literal)
示例
SELECT * FROM x WHERE column_1 IN (1,3);
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 1 | 2 |
+----------+----------+
SELECT * FROM x WHERE column_1 NOT IN (1,3);
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 2 | 4 |
+----------+----------+
SELECT 子句中的子查询
SELECT 子句子查询把内层查询返回的值用在外层查询的 SELECT 列表中。
SELECT 子句仅支持 标量子查询,即每次执行内层查询
只返回一个值。
返回的值可以逐行不同。
SELECT [expression1[, expression2, ..., expressionN],] (<subquery>)
注意:SELECT 子句子查询可以用来替代 JOIN
操作。
示例
SELECT
column_1,
(
SELECT
first_value(string)
FROM
y
WHERE
number = x.column_1
) AS "numeric string"
FROM
x;
+----------+----------------+
| column_1 | numeric string |
+----------+----------------+
| 1 | one |
| 2 | two |
+----------+----------------+
FROM 子句中的子查询
FROM 子句子查询返回一组结果,外层查询再对这组结果进行
查询和运算。
SELECT expression1[, expression2, ..., expressionN] FROM (<subquery>)
示例
下面的查询返回每个房间最大值的平均值。 内层查询返回每个房间中每个字段的最大值。 外层查询使用内层查询的结果,返回每个字段的平均 最大值。
SELECT
column_2
FROM
(
SELECT
*
FROM
x
WHERE
column_1 > 1
);
+----------+
| column_2 |
+----------+
| 4 |
+----------+
WHERE 子句中的子查询
WHERE 子句子查询将表达式与子查询的结果进行比较,
返回 true 或 false。
求值为 false 或 NULL 的行会从结果中过滤掉。
WHERE 子句支持相关(correlated)与非相关(non-correlated)子查询,
也支持标量与非标量子查询(取决于谓词表达式中使用的运算符)。
SELECT
expression1[, expression2, ..., expressionN]
FROM
<measurement>
WHERE
expression operator (<subquery>)
注意:WHERE 子句子查询可以用来替代 JOIN
操作。
示例
WHERE 子句与标量子查询
下面的查询返回所有 column_2 值高于 y 中所有 number 值
平均值的行。
SELECT
*
FROM
x
WHERE
column_2 > (
SELECT
AVG(number)
FROM
y
);
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 2 | 4 |
+----------+----------+
WHERE 子句与非标量子查询
非标量子查询必须使用 [NOT] IN 或 [NOT] EXISTS 运算符,
并且只能返回一列。
返回列中的值会作为一个列表来求值。
下面的查询返回表 x 中 column_2 值位于表
y 中字符串长度大于 3 的数字列表内的所有行。
SELECT
*
FROM
x
WHERE
column_2 IN (
SELECT
number
FROM
y
WHERE
length(string) > 3
);
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 2 | 4 |
+----------+----------+
WHERE 子句与相关子查询
下面的查询返回表 x 中 column_2 值大于表 y 中 string 值
平均长度的行。
WHERE 子句中的子查询使用外层
查询的 column_1 值,返回该特定值对应的 string 值平均长度。
SELECT
*
FROM
x
WHERE
column_2 > (
SELECT
AVG(length(string))
FROM
y
WHERE
number = x.column_1
);
+----------+----------+
| column_1 | column_2 |
+----------+----------+
| 2 | 4 |
+----------+----------+
HAVING 子句中的子查询
HAVING 子句子查询把 SELECT 子句中聚合函数返回的聚合值
组成的表达式与子查询的结果进行比较,返回 true 或 false。
求值为 false 的行会从结果中过滤掉。
HAVING 子句支持相关与非相关子查询,
也支持标量与非标量子查询(取决于谓词表达式中使用的运算符)。
SELECT
aggregate_expression1[, aggregate_expression2, ..., aggregate_expressionN]
FROM
<measurement>
WHERE
<conditional_expression>
GROUP BY
column_expression1[, column_expression2, ..., column_expressionN]
HAVING
expression operator (<subquery>)
示例
下面的查询计算表 y 中偶数和奇数的平均值,
并返回等于表 x 中 column_1 最大值的那些平均值。
HAVING 子句与标量子查询
SELECT
AVG(number) AS avg,
(number % 2 = 0) AS even
FROM
y
GROUP BY
even
HAVING
avg = (
SELECT
MAX(column_1)
FROM
x
);
+-------+--------+
| avg | even |
+-------+--------+
| 2 | false |
+-------+--------+
HAVING 子句与非标量子查询
非标量子查询必须使用 [NOT] IN 或 [NOT] EXISTS 运算符,
并且只能返回一列。
返回列中的值会作为一个列表来求值。
下面的查询计算表 y 中偶数和奇数的平均值,
并返回位于表 x 的 column_1 中的那些平均值。
SELECT
AVG(number) AS avg,
(number % 2 = 0) AS even
FROM
y
GROUP BY
even
HAVING
avg IN (
SELECT
column_1
FROM
x
);
+-------+--------+
| avg | even |
+-------+--------+
| 2 | false |
+-------+--------+
子查询的分类(Subquery Categories)
根据子查询的行为,可以将其归入以下一个或多个类别:
相关子查询(Correlated subqueries)
在相关子查询中,内层查询依赖于当前正在处理的行 的值。
注意:DataFusion 会在内部把相关子查询改写为 JOIN 以 提升性能。一般来说,相关子查询的性能不如 非相关子查询。
非相关子查询(Non-correlated subqueries)
在非相关子查询中,内层查询_不_依赖外层 查询,可以独立执行。 内层查询先执行,然后把结果传递给外层查询。
标量子查询(Scalar subqueries)
标量子查询返回单个值(一行中的一列)。 如果没有返回任何行,子查询返回 NULL。
非标量子查询(Non-scalar subqueries)
非标量子查询返回 0 行、1 行或多行,每行可以 包含 1 列或多列。对每一列来说,如果没有可返回的值, 子查询返回 NULL。如果没有符合条件的行,子查询 返回 0 行。