6.15. 子查询表达式

本节描述 PostgreSQL 里面能用的 SQL 兼容的子查询表达式.所有本节中成文的表达式 都返回布尔值(真/假)结果.

6.15.1. EXISTS

EXISTS ( subquery )

EXISTS 的参数是一个任意的SELECT语句, 或者说子查询.系统对子查询进行运算以判断它 是否返回行.如果它至少返回一行,那么 EXISTS 的结果就为"真"; 如果子查询没有返回行,那么 EXISTS 的结果是"假"

子查询可以引用来自周围的查询的变量,这些变量在该子查询的任何一次 计算中都起常量的作用.

这个子查询通常只是运行到能判断它是否可以生成至少一行为止, 而不是等到全部结束.在这里写任何有副作用的子查询都是不明智的 (比如调用序列函数);这些副作用是否发生是很难判断的.

因为结果只取决于是否会返回行,而不取决于这些行的内容, 所以这个子查询的输出列表通常是无关紧要的.一个常用的 编码习惯是用下面的形式写所有的EXISTS测试 EXISTS(SELECT 1 WHERE ...).不过这条规则有例外, 比如那些使用 INTERSECT 的子查询.

下面这个简单的例子类似在col2上的一次内联接,但是它为每个 tab1的行生成最多一个输出,即时存在多个匹配tab2的行也如此∶

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

6.15.2. IN (标量形式)

expression IN (value[, ...])

IN 的这种形式的右手边是一个用圆括弧括起来的 标量表达式的列表.如果左手边的表达式的结果等于任何右手边表达式的结果 中的一个,那么整个表达式的结果就是"真".它是下面的表示法的缩写

expression = value1
OR
expression = value2
OR
...

请注意如果左手边的表达式生成 NULL,或者没有相等的右手边数值, 并且右手边表达式至少有一个生成 NULL,那么 IN 构造的 结果将为 NULL,而不是 FALSE.这个行为是遵照 SQL 处理布尔和 NULL 值组合时的规则定的.

注意: 这种形式的 IN 并非真的是子查询表达式, 但是好像把它很子查询 IN 的文档放在一起好像是最好的.

6.15.3. IN (子查询形式)

expression IN (subquery)+ 

IN 的这种形式的右手边是一个圆括弧括起来的子查询, 它必须只返回一列.左手边表达式对子查询的结果的每一行进行一次计算和 比较.如果找到任何等于子查询行的情况,那么 IN 的结果就是 "真".如果没有找到相等行,那么结果是"假"(包括子查询没有返回任何行 的特殊例子).

请注意如果左手边表达式生成 NULL,或者没有相等的右手边数值, 并且至少有一个右手边行生成 NULL,那么 IN 构造的 结果将是 NULL,而不是 FALSE.这个行为是遵照 SQL 处理布尔和 NULL 值组合时的规则定的.

EXISTS 一样,假设子查询将被完成运行完全是不明智的.

(expression, expression[, ...]) IN (subquery)

这种形式的 IN 的右手边是一个圆括弧括起来的子查询, 它必须返回和左手边表达式列表中完全一样多的字段. 左手边表达式就子查询结果的每一行进行计算很比较.如果找到任意 相等的子查询行,则 IN 的结果为"真".如果没有找到相等行, 那么结果为"假"(包括子查询不返回行的特殊例子).

通常,表达式或者子查询行里的 NULL 是按照 SQL 布尔表达式的一般规则 进行组合的.如果两个行对应的成员都是非空并且相等,那么认为这两行 相等;如果任意对应成员为非空且不等,那么该两行不等; 否则这样的行比较的结果是未知(NULL).如果所有行的结果要么是不等, 要么是 NULL,并且至少有一个 NULL,那么 IN 的结果是 NULL.

6.15.4. NOT IN (标量形式)

expression NOT IN (value[, ...])

这种形式的 NOT IN 的右手边是一个圆括弧括起来的 标量表达式的列表.如果左手边表达式的结果与所有右手边表达式的结果 都不相等,那么结果是"真".它是下面表示法的缩写

expression <> value1
AND
expression <> value2
AND
...

请注意如果左手边表达式生成 NULL,或者存在相等的右手边数值, 并且至少有一个右手边行生成 NULL,那么 NOT IN 构造的 结果将是 NULL,而不是 FALSE.这个行为是遵照 SQL 处理布尔和 NULL 值组合时的规则定的.

技巧: x NOT IN y 在任何情况下都等效于 NOT (x IN y). 不过,NULL 在 NOT IN 里用的时候比在 IN 里用的时候更容易让新手犯错.所以最好还是尽可能用正逻辑 表示你的条件.

6.15.5. NOT IN (子查询形式)

expression NOT IN (subquery)

NOT IN 的这种形式的右手边是一个圆括弧括起来的子查询, 它必须只返回一列.左手边表达式对子查询的结果的每一行进行一次计算和 比较.如果只出现不等于子查询行的情况,那么 NOT IN 的结果就是 "真".(包括子查询没有返回任何行的特殊例子). 如果找到相等行,那么结果是"假"

请注意如果左手边表达式生成 NULL,或者没有相等的右手边数值, 并且至少有一个右手边行生成 NULL,那么 NOT IN 构造的 结果将是 NULL,而不是 TRUE.这个行为是遵照 SQL 处理布尔和 NULL 值组合时的规则定的.

EXISTS 一样,假设子查询将被完成运行完全是不明智的.

(expression, expression[, ...]) NOT IN (subquery)

这种形式的 NOT IN 的右手边是一个圆括弧括起来的子查询, 它必须返回和左手边表达式列表中完全一样多的字段. 左手边表达式就子查询结果的每一行进行计算很比较.如果只存在不 相等的子查询行,则 NOT IN 的结果为 TRUE. (包括子查询不返回行的特殊例子). 如果找到任何相等行, 那么结果为 FALSE.

通常,表达式或者子查询行里的 NULL 是按照 SQL 布尔表达式的一般规则 进行组合的.如果两个行对应的成员都是非空并且相等,那么认为这两行 相等;如果任意对应成员为非空且不等,那么该两行不等; 否则这样的行比较的结果是未知(NULL).如果所有行的结果要么是不等, 要么是 NULL,并且至少有一个 NULL,那么 NOT IN 的结果是 NULL.

6.15.6. ANY/SOME

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

ANY 的这种形式的右手边是一个圆括弧括起来的子查询, 它必须只返回一列.左手边表达式将使用给出的 operator对子查询的结果的每一行进行一次计算和 比较.该操作符必须生成布尔结果. 如果获得任何真值结果,那么 ANY 的结果就是 "真".如果没有找到真值结果,那么结果是"假"(包括子查询没有返回任何行 的特殊例子).

SOMEANY 的同意词. IN 等效于 = ANY

请注意如果没有任何成功并且至少有一个右手边行为该操作符结果生成 NULL, 那么 ANY 构造的结果将是 NULL,而不是 FALSE. 这个行为是遵照 SQL 处理布尔和 NULL 值组合时的规则定的.

EXISTS 一样,假设子查询将被完成运行完全是不明智的.

(expression [, expression ...]) operator ANY (subquery)
(expression [, expression ...]) operator SOME (subquery)

ANY 的这种形式的右手边是一个圆括弧括起来的子查询, 它必须返回和左手边列表给出的表达式一样多的列.左手边表达式将使用给出的 operator对子查询的结果的每一行进行一次计算和 比较.目前系统只允许使用 =<> 操作符处理逐行的 ANY 查询. 如果分别找到相等或者不相等的行,那么 ANY 的结果就是 "真".如果没有找到这样的行,那么结果是"假"(包括子查询没有返回任何行 的特殊例子).

通常,表达式或者子查询行里的 NULL 是按照 SQL 布尔表达式的一般规则 进行组合的.如果两个行对应的成员都是非空并且相等,那么认为这两行 相等;如果任意对应成员为非空且不等,那么该两行不等; 否则这样的行比较的结果是未知(NULL).如果至少有一个 NULL 行结果, 那么 ANY 的结果将是TRUE 或者 NULL.

6.15.7. ALL

expression operator ALL(subquery)

ALL 的这种形式的右手边是一个圆括弧括起来的子查询, 它必须只返回一列.左手边表达式将使用给出的 operator对子查询的结果的每一行进行一次计算和 比较.该操作符必须生成布尔结果. 如果所有行的结果都为"真",(包括子查询没有返回任何行的特殊例子). 那么 ALL 的结果就是 "真".如果没有存在任何假值结果,那么结果是"假"

NOT IN 等效于 <> ALL

请注意如果没有运算失败但是至少有一个右手边行为该操作符的结果 生成 NULL 值,那么 ALL 构造的结果将是 NULL,而不是 TRUE. 这个行为是遵照 SQL 处理布尔和 NULL 值组合时的一般规则定的.

EXISTS 一样,假设子查询将被完成运行完全是不明智的.

(expression, expression[, ...]) operator ALL (subquery)

ALL 的这种形式的右手边是一个圆括弧括起来的子查询, 它必须返回和左手边列表给出的表达式一样多的列.左手边表达式将使用给出的 operator对子查询的结果的每一行进行一次计算和 比较.目前系统只允许使用 =<> 操作符处理逐行的 ALL 查询. 如果所有子查询都是相等或者不相等的行,那么 ALL 的结果就是 "真".(包括子查询没有返回任何行的特殊例子). 如果分别有任何不相等或者相等的行,那么结果是"假"

通常,表达式或者子查询行里的 NULL 是按照 SQL 布尔表达式的一般规则 进行组合的.如果两个行对应的成员都是非空并且相等,那么认为这两行 相等;如果任意对应成员为非空且不等,那么该两行不等; 否则这样的行比较的结果是未知(NULL).如果至少有一个 NULL 行结果, 那么 ALL 的结果就不可能是TRUE;它将会是 FALSE 或者 NULL.

6.15.8. 逐行比较

(expression [, expression ...]) operator (subquery)
(expression [, expression ...]) operator (expression [, expression ...])

左手边是一个标量表达式列表.右手边可以是一个等长的标量表达式的列表, 或者一个圆括弧括起来的子查询,该查询必须返回很左手边表达式书目完全 一样的字段.另外,该子查询不能返回超过一行的数量.(如果它返回零行, 那么结果就是 NULL.)左手边逐行与右手边的子查询结果行,或者右手边 表达式列表进行比较.目前,只允许使用 =<> 操作符进行逐行比较. 如果两行分别是相等或者不等,那么结果为"真"

通常,表达式或者子查询行里的 NULL 是按照 SQL 布尔表达式的一般规则 进行组合的.如果两个行对应的成员都是非空并且相等,那么认为这两行 相等;如果任意对应成员为非空且不等,那么该两行不等; 否则这样的行比较的结果是未知(NULL).