Postgresql 中文操作指南

9.23. Subquery Expressions #

此部分描述 PostgreSQL 中可用的符合 SQL 的子查询表达式。此部分中记录的所有表达式形式均返回布尔值(真/假)结果。

9.23.1. EXISTS #

EXISTS (subquery)

EXISTS 的参数是任意的 SELECT 语句或 subquery。对子查询进行评估,以确定它是否返回任何行。如果它返回至少一行,则 EXISTS 的结果为“真”;如果子查询不返回任何行,则 EXISTS 的结果为“假”。

子查询可以参考周围查询中的变量,这些变量在子查询的任何一次评估期间充当常量。

通常仅执行子查询足够长的时间以确定是否返回至少一行,而不是一直执行到完成。编写有副作用(例如调用序列函数)的子查询是不明智的;这些副作用是否发生可能是不可预测的。

由于结果只取决于是否返回任何行,而不取决于这些行的内容,因此子查询的输出列表通常并不重要。常见的编码约定是以 EXISTS(SELECT 1 WHERE …​) 形式编写所有 EXISTS 测试。然而,有例外情况,例如使用 INTERSECT 的子查询。

这个简单示例类似于对 col2 的内部联接,但是即使有几个匹配的 tab2 行,它也只为每个 tab1 行生成最多一个输出行:

SELECT col1
FROM tab1
WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2);

9.23.2. IN #

expression IN (subquery)

右侧是一个括起来的子查询,它必须只返回一列。对左表达式进行评估,并将其与子查询结果的每一行进行比较。如果找到任何相等的子查询行,则 IN 结果为“真”。如果没有找到相等的行(包括子查询不返回任何行的情况),则该结果为“假”。

请注意,如果左表达式产生 NULL,或者如果没有相等的右侧值,且至少有一个右侧行产生 NULL,则 IN 构造的结果将为 NULL,而非假。这与 SQL 关于 NULL 值布尔组合的正常规则是一致的。

EXISTS 一样,假设子查询将被完整评估是不明智的。

row_constructor IN (subquery)

此形式 IN 的左侧是一个行构造函数,如 Section 4.2.13 中所述。右侧是一个加了括号的子查询,该子查询必须返回与左侧行中的表达式数量完全相同数量的列。左侧表达式在子查询结果的每一行上按行评估并比较。如果找到任何相等的子查询行,IN 的结果为“true”。如果找不到相等行,则结果为“false”(包括子查询未返回任何行的情况)。

与往常一样,行中的 NULL 值按照 SQL 布尔表达式的正常规则组合。如果所有相应的成员都为非 NULL 且相等,则认为两行相等;如果任何相应的成员为非 NULL 且不相等,则行不相等;否则,该行比较的结果未知(NULL)。如果所有按行比较的结果要么不相等,要么为 NULL,并且至少有一个 NULL,则 IN 的结果为 NULL。

9.23.3. NOT IN #

expression NOT IN (subquery)

右侧是一个括起来的子查询,它必须只返回一列。对左表达式进行评估,并将其与子查询结果的每一行进行比较。如果仅找到不相等的子查询行(包括子查询不返回任何行的情况),则 NOT IN 结果为“真”。如果找到任何相等的行,则该结果为“假”。

注意,如果左侧表达式生成 null,或者如果不存在相等右侧值且至少有一个右侧行生成 null,NOT IN 构造的结果将是 null,而不是 true。这符合 SQL 关于 null 值布尔组合的正常规则。

EXISTS 一样,假设子查询将被完整评估是不明智的。

row_constructor NOT IN (subquery)

此形式 NOT IN 的左侧是一个行构造函数,如 Section 4.2.13 中所述。右侧是一个加了括号的子查询,该子查询必须返回与左侧行中的表达式数量完全相同数量的列。左侧表达式在子查询结果的每一行上按行评估并比较。如果仅找到不相等的子查询行(包括子查询未返回任何行的情况),NOT IN 的结果为“true”。如果找到任何相等行,则结果为“false”。

与往常一样,行中的 null 值根据 SQL 布尔表达式的正常规则组合。如果所有成员都为非空且相等,则两行被认为相等;如果任何相应的成员为非空且不相等,则两行不相等;否则,该行比较的结果未知(null)。如果所有按行结果都为不相等或 null(其中至少有一个为 null),则 NOT IN 的结果为 null。

9.23.4. ANY/SOME #

expression operator ANY (subquery)
expression operator SOME (subquery)

右侧是一个带括号的子查询,它必须返回恰好一列。左侧表达式经过计算,并使用指定的 operator 与子查询结果的每一行进行比较,该 operator 必须生成一个布尔结果。如果获得任何真结果,ANY 的结果为“true”。如果没有找到任何真结果(包括子查询没有返回任何行的情况),结果为“false”。

SOMEANY 的同义词。IN 等效于 = ANY

注意,如果不存在任何成功并且至少有一个右侧行针对算子的结果生成 null,则 ANY 构造的结果将为 null,而不是 false。这符合 SQL 关于 null 值布尔组合的正常规则。

EXISTS 一样,假设子查询将被完整评估是不明智的。

row_constructor operator ANY (subquery)
row_constructor operator SOME (subquery)

此形式 ANY 的左侧是一个行构造函数,如 Section 4.2.13 中所述。右侧是一个加了括号的子查询,该子查询必须返回与左侧行中的表达式数量完全相同数量的列。左侧表达式使用给定的 operator 在子查询结果的每一行上按行评估并比较。如果比较对任何子查询行返回 true,ANY 的结果为“true”。如果比较对每个子查询行(包括子查询未返回任何行的情况)返回 false,则结果为“false”。如果没有与子查询行的比较返回 true,并且至少有一个比较返回 NULL,则结果为 NULL。

有关行构造函数比较的含义,请参阅 Section 9.24.5

9.23.5. ALL #

expression operator ALL (subquery)

右侧是一个带括号的子查询,它必须返回恰好一列。左侧表达式经过计算,并使用指定的 operator 与子查询结果的每一行进行比较,该 operator 必须生成一个布尔结果。如果所有行都生成 true(包括子查询没有返回任何行的情况),ALL 的结果为“true”。如果找到任何 false 结果,结果为“false”。如果没有与子查询行的比较返回 false,且至少有一个比较返回 NULL,则结果为 NULL。

NOT IN 等效于 <> ALL

EXISTS 一样,假设子查询将被完整评估是不明智的。

row_constructor operator ALL (subquery)

此形式 ALL 的左侧是一个行构造函数,如 Section 4.2.13 中所述。右侧是一个加了括号的子查询,该子查询必须返回与左侧行中的表达式数量完全相同数量的列。左侧表达式使用给定的 operator 在子查询结果的每一行上按行评估并比较。如果比较对所有子查询行(包括子查询未返回任何行的情况)返回 true,ALL 的结果为“true”。如果比较对任何子查询行返回 false,则结果为“false”。如果没有与子查询行的比较返回 false,并且至少有一个比较返回 NULL,则结果为 NULL。

有关行构造函数比较的含义,请参阅 Section 9.24.5

9.23.6. Single-Row Comparison #

row_constructor operator (subquery)

左侧是一个行构造函数,如 Section 4.2.13 中所述。右侧是一个加了括号的子查询,该子查询必须返回与左侧行中的表达式数量完全相同数量的列。而且,该子查询不能返回多于一行。(如果返回零行,则结果为 null。)左侧在单一子查询结果行上按行评估并比较。

有关行构造函数比较的含义,请参阅 Section 9.24.5