子查询(也称为内部查询或嵌套查询)是查询中的查询。子查询可用于 SELECT、FROM、WHERE 和 HAVING 子句。
子查询运算符
[ NOT ] EXISTS
EXISTS 运算符返回在相关子查询 为该行产生一个或多个匹配项的所有行。NOT EXISTS 返回在相关子查询 未为该行产生匹配项的所有行。仅支持相关子查询。
语法
[ NOT ] IN
IN 运算符返回给定表达式的值可以在相关子查询 的结果中找到的所有行。NOT IN 返回给定表达式的值在子查询或值列表的结果中找不到的所有行。
语法
expression [NOT] IN (subquery|list-literal)
示例
使用查询查看 IN 示例
SELECT
time,
room,
temp
FROM
home
WHERE
room IN (
SELECT
DISTINCT room
FROM
home_actions
)
SELECT
time,
room,
temp
FROM
home
WHERE
room NOT IN (
SELECT
DISTINCT room
FROM
home_actions
)
使用列表字面量查看 IN 示例
SELECT
time,
room,
temp
FROM home
WHERE room IN ('Bathroom', 'Bedroom', 'Kitchen')
SELECT
time,
room,
temp
FROM home
WHERE room NOT IN ('Bathroom', 'Bedroom', 'Kitchen')
SELECT 子句中的子查询
SELECT 子句中的子查询使用内查询返回的值作为外查询 SELECT 列表的一部分。SELECT 子句仅支持返回内查询每次执行单个值的标量子查询。返回值可以对每行是唯一的。
语法
SELECT [expression1[, expression2, ..., expressionN],] (<subquery>)
SELECT 子句中的子查询可用作 JOIN 操作的替代。
示例
FROM 子句中的子查询
FROM 子句中的子查询返回一个结果集,该结果集随后被外查询查询和操作。
语法
SELECT expression1[, expression2, ..., expressionN] FROM (<subquery>)
示例
查看 FROM 子句子查询示例
以下查询返回每个房间最大值的平均值。内查询返回每个房间每个字段的最大值。外查询使用内查询的结果并返回每个字段的平均最大值。
SELECT
AVG(max_co) AS avg_max_co,
AVG(max_hum) AS avg_max_hum,
AVG(max_temp) AS avg_max_temp
FROM
(
SELECT
room,
MAX(co) AS max_co,
MAX(hum) AS max_hum,
MAX(temp) AS max_temp
FROM
home
GROUP BY
room
)
内查询结果
| room | max_co | max_hum | max_temp |
|---|
| 客厅 | 17 | 36.4 | 22.8 |
| 厨房 | 26 | 36.9 | 23.3 |
外查询结果
| avg_max_co | avg_max_hum | avg_max_temp |
|---|
| 21.5 | 36.7 | 23.1 |
WHERE 子句中的子查询
WHERE 子句中的子查询将表达式与子查询的结果进行比较,并返回true 或false。值为false 或 NULL 的行将从结果中过滤掉。WHERE 子句支持相关和非相关子查询以及标量和非标量子查询(取决于谓词表达式中使用的运算符)。
语法
SELECT
expression1[, expression2, ..., expressionN]
FROM
<measurement>
WHERE
expression operator (<subquery>)
WHERE 子句中的子查询可用作 JOIN 操作的替代。
示例
带标量子查询的 WHERE 子句
以下查询返回 temp 值大于所有 temp 值平均值的点。子查询返回平均 temp 值。
SELECT
*
FROM
home
WHERE
temp > (
SELECT
AVG(temp)
FROM
home
)
内查询结果
| AVG(home.temp) |
|---|
| 22.396153846153844 |
外查询结果
| co | hum | room | temp | time |
|---|
| 0 | 36.2 | 厨房 | 23 | 2022-01-01T09:00:00Z |
| 0 | 36.1 | 厨房 | 22.7 | 2022-01-01T10:00:00Z |
| 0 | 36 | 厨房 | 22.4 | 2022-01-01T11:00:00Z |
| 0 | 36 | 厨房 | 22.5 | 2022-01-01T12:00:00Z |
| 1 | 36.5 | 厨房 | 22.8 | 2022-01-01T13:00:00Z |
| 1 | 36.3 | 厨房 | 22.8 | 2022-01-01T14:00:00Z |
| 3 | 36.2 | 厨房 | 22.7 | 2022-01-01T15:00:00Z |
| 7 | 36 | 厨房 | 22.4 | 2022-01-01T16:00:00Z |
| 9 | 36 | 厨房 | 22.7 | 2022-01-01T17:00:00Z |
| 18 | 36.9 | 厨房 | 23.3 | 2022-01-01T18:00:00Z |
| 22 | 36.6 | 厨房 | 23.1 | 2022-01-01T19:00:00Z |
| 26 | 36.5 | 厨房 | 22.7 | 2022-01-01T20:00:00Z |
| 0 | 36 | 客厅 | 22.4 | 2022-01-01T13:00:00Z |
| 4 | 36 | 客厅 | 22.4 | 2022-01-01T16:00:00Z |
| 5 | 35.9 | 客厅 | 22.6 | 2022-01-01T17:00:00Z |
| 9 | 36.2 | 客厅 | 22.8 | 2022-01-01T18:00:00Z |
| 14 | 36.3 | 客厅 | 22.5 | 2022-01-01T19:00:00Z |
带非标量子查询的 WHERE 子句
非标量子查询必须使用 [NOT] IN 或 [NOT] EXISTS 运算符,并且只能返回单个列。返回列中的值被评估为一个列表。
以下查询返回 home 度量中的所有点,这些点的 associated timestamp 与 home_actions 度量中的 warn 级别的警报的 timestamp 相同。
SELECT
*
FROM
home
WHERE
time IN (
SELECT
DISTINCT time
FROM
home_actions
WHERE
level = 'warn'
)
内查询结果
| time |
|---|
| 2022-01-01T18:00:00Z |
| 2022-01-01T19:00:00Z |
| 2022-01-01T20:00:00Z |
外查询结果
| co | hum | room | temp | time |
|---|
| 18 | 36.9 | 厨房 | 23.3 | 2022-01-01T18:00:00Z |
| 9 | 36.2 | 客厅 | 22.8 | 2022-01-01T18:00:00Z |
| 26 | 36.5 | 厨房 | 22.7 | 2022-01-01T20:00:00Z |
| 17 | 36.4 | 客厅 | 22.2 | 2022-01-01T20:00:00Z |
| 22 | 36.6 | 厨房 | 23.1 | 2022-01-01T19:00:00Z |
| 14 | 36.3 | 客厅 | 22.5 | 2022-01-01T19:00:00Z |
HAVING 子句中的子查询
HAVING 子句中的子查询将使用 SELECT 子句中的聚合函数返回的聚合值的表达式与子查询的结果进行比较,并返回true 或false。值为false 或 NULL 的行将从结果中过滤掉。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>)
示例
带标量子查询的 HAVING 子句
以下查询返回平均 temp 值大于中值 temp 值的两个小时时间段。
SELECT
DATE_BIN(INTERVAL '2 hours', time) AS "2-hour block",
AVG(temp) AS avg_temp
FROM
home
GROUP BY
1
HAVING
avg_temp > (
SELECT
MEDIAN(temp)
FROM
home
)
内查询结果
外查询结果
| 2小时块 | avg_temp |
|---|
| 2022-01-01T12:00:00Z | 22.475 |
| 2022-01-01T16:00:00Z | 22.525 |
| 2022-01-01T18:00:00Z | 22.925 |
| 2022-01-01T14:00:00Z | 22.525 |
带非标量子查询的 HAVING 子句
非标量子查询必须使用 [NOT] IN 或 [NOT] EXISTS 运算符,并且只能返回单个列。返回列中的值被评估为一个列表。
以下查询返回 2 小时时间窗口内的最大 co 和 temp 值,其中与时间窗口关联的 time 值也与 home_actions 度量中的警告相关联。
SELECT
date_bin(INTERVAL '2 hours', time) AS "2-hour block",
max(co) AS max_co,
max(temp) as max_temp
FROM
home
GROUP BY
1,
room
HAVING
"2-hour block" IN (
SELECT
DISTINCT time
FROM
home_actions
WHERE
level = 'warn'
)
内查询结果
| time |
|---|
| 2022-01-01T18:00:00Z |
| 2022-01-01T19:00:00Z |
| 2022-01-01T20:00:00Z |
外查询结果
| 2小时块 | max_co | max_temp |
|---|
| 2022-01-01T18:00:00Z | 14 | 22.8 |
| 2022-01-01T18:00:00Z | 22 | 23.3 |
| 2022-01-01T20:00:00Z | 17 | 22.2 |
| 2022-01-01T20:00:00Z | 26 | 22.7 |
子查询的类别
SQL 子查询可以根据子查询的行为归类为以下一项或多项
在相关子查询中,内查询依赖于正在处理的当前行的值。
在下面的查询中,内查询(SELECT temp_avg FROM weather WHERE location = home.room)依赖于外查询(SELECT time, room, temp FROM home)中的数据(home.room),因此是相关子查询。
SELECT
time,
room,
temp
FROM
home
WHERE
temp = (
SELECT
temp_avg
FROM
weather
WHERE
location = home.room
)
由于相关子查询依赖于外查询,并且通常必须为外查询返回的每一行执行,因此相关子查询的性能低于非相关子查询。
在非相关子查询中,内查询不依赖于外查询,而是独立执行。内查询首先执行,然后将结果传递给外查询。
在下面的查询中,内查询(SELECT MIN(temp_avg) FROM weather)可以独立于外查询(SELECT time, temp FROM home)运行,因此是非相关子查询。
SELECT
time,
temp
FROM
home
WHERE
temp < (
SELECT
MIN(temp_avg)
FROM
weather
)
标量子查询
标量子查询返回单个值(一行一列)。如果没有返回行,子查询将返回 NULL。
下面的示例子查询返回指定列的平均值。此值为单个标量值。
SELECT * FROM home WHERE co > (SELECT avg(co) FROM home)
非标量子查询
非标量子查询返回 0、1 或多行,每行可能包含 1 列或多列。对于每一列,如果没有要返回的值,则子查询返回 NULL。如果没有符合条件的行返回,则子查询返回 0 行。
下面的示例子查询返回列中的所有不同值。将返回多个值。
SELECT * FROM home WHERE room IN (SELECT DISTINCT room FROM home_actions)
支持和反馈
感谢您成为我们社区的一员!我们欢迎并鼓励您对 InfluxDB 3 Core 和本文档提供反馈和错误报告。要获得支持,请使用以下资源
具有年度合同或支持合同的客户可以 联系 InfluxData 支持。