子查询表达式
子查询表达式¶
本节描述SeaboxSQL中可用的SQL兼容的子查询表达式。所有本节中成文的表达式都返回布尔值(真/假)结果。
EXISTS/NOT EXISTS
¶
- 语法
EXISTS (subquery)
- 描述
-
EXISTS
的参数是一个任意的SELECT
语句,或者说子查询。系统对子查询进行运算以判断它是否返回行。如果它至少返回一行,那么EXISTS
的结果就为“真”;如果子查询没有返回行,那么EXISTS
的结果是“假”。子查询可以引用来自周围的查询的变量,这些变量在该子查询的任何一次计算中都起常量的作用。
这个子查询通常只是运行到能判断它是否可以返回至少一行为止,而不是等到全部结束。在这里写任何有副作用的子查询都是不明智的(例如调用序列函数);这些副作用是否发生是很难判断的。
因为结果只取决于是否会返回行,而不取决于这些行的内容,所以这个子查询的输出列表通常是无关紧要的。一个常用的编码习惯是用
EXISTS(SELECT 1 WHERE ...)
的形式写所有的EXISTS
测试。不过这条规则有例外,例如那些使用INTERSECT
的子查询。 - 示例
-
以下示例为
EXISTS/NOT EXISTS
常用类型语句,注意关于NULL值的表现与IN/NOT IN
的区别。seaboxsql=# create table subquery_test1(a int); CREATE TABLE seaboxsql=# create table subquery_test2(a int); CREATE TABLE seaboxsql=# insert into subquery_test1 select generate_series(1,10); INSERT 0 10 seaboxsql=# insert into subquery_test1 values(null); INSERT 0 1 seaboxsql=# insert into subquery_test2 select generate_series(1,5); INSERT 0 5 seaboxsql=# insert into subquery_test2 values(null); INSERT 0 1 seaboxsql=# select * from subquery_test1 a where exists(select 1 from subquery_test2 b where a.a=b.a) ; a --- 1 2 3 4 5 (5 rows) seaboxsql=# select * from subquery_test1 a where not exists(select 1 from subquery_test2 b where a.a=b.a) ; a ---- 6 7 8 9 10 (6 rows)
IN/NOT IN
¶
- 语法
expression IN/NOT IN (subquery)
,row_constructor IN/NOT IN (subquery)
- 描述
-
右手边是一个圆括弧括起来的子查询, 它必须正好只返回一个列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到任何等于子查询行的情况,那么
IN
的结果就是“真”。如果没有找到相等行,那么结果是“假”(包括子查询没有返回任何行的情况)。请注意如果左手边表达式得到空值,或者没有相等的右手边值,并且至少有一个右手边行得到空值,那么
IN
结构的结果将是空值,而不是假。这个行为是遵照SQL 处理空值的一般规则的。和
EXISTS
一样,假设子查询将被完成运行完全是不明智的。row_constructor
形式的IN
的左手边是一个行构造器。右手边是一个圆括弧子查询,它必须返回和左手边返回的行中表达式所构成的完全一样多的列。左手边表达式将被计算并与子查询结果逐行进行比较。如果找到任意相等的子查询行,则IN
的结果为“真”。如果没有找到相等行,那么结果为“假”(包括子查询不返回行的情况)。NOT IN
情况与IN
正好相反。表达式或者子查询行里的空值是按照 SQL 布尔表达式的一般规则进行组合的,特别注意NULL值的处理。如果两个行对应的成员都非空并且相等,那么认为这两行相等;如果任意对应成员为非空且不等,那么这两行不等;否则这样的行比较的结果是未知(空值)。如果所有行的结果要么是不等, 要么是空值,并且至少有一个空值,那么
IN
的结果是空值。 - 示例
-
``` sql seaboxsql=# select * from subquery_test1 where a in(select a from subquery_test2); a
1 2 3 4 5 (5 rows)seaboxsql=# select * from subquery_test1 where a not in(select a from subquery_test2); a
(0 rows)
seaboxsql=# select * from subquery_test1 where a not in(select a from subquery_test2 where a is not null); a
6 7 8 9 10 (5 rows)
seaboxsql=# select * from subquery_test1 where a not in(select a from subquery_test2 ) and a is not null; a
(0 rows) ```
ANY/SOME
¶
- 语法
expression operator ANY/SOME (subquery)
,row_constructor operator ANY/SOME (subquery)
- 描述
-
expression
形式的右手边是一个圆括弧括起来的子查询, 它必须返回正好一个列。左手边表达式将被计算并使用给出的操作符
对子查询结果逐行进行比较。如果获得任何真值结果,那么ANY
的结果就是“真”。如果没有找到真值结果,那么结果是“假”(包括子查询没有返回任何行的情况)。row_constructor
形式的左手边是一个行构造器,如行构造器所述。右手边是一个圆括弧括起来的子查询,它必须返回和左手边列表给出的表达式一样多的列。左手边表达式将被计算并使用给出的操作符
对子查询结果逐行进行比较。如果比较为任何子查询行返回真,则ANY
的结果为“真”。如果比较对每一个子查询行都返回假,则结果为“假”(包括子查询不返回行的情况)。如果比较不对任何行返回真并且至少对一行返回NULL,则结果为 NULL。SOME
是ANY
的同义词。IN
等价于= ANY
。- 注意: 如果没有任何成功并且至少有一个右手边行为该操作符结果生成空值, 那么
ANY
结构的结果将是空值,而不是假。 这个行为是遵照 SQL处理空值布尔组合的一般规则制定的。
- 注意: 如果没有任何成功并且至少有一个右手边行为该操作符结果生成空值, 那么
- 示例
-
注意以下示例中不同操作符的表现。
seaboxsql=# select * from subquery_test1 where a=some(select a from subquery_test2 ) and a is not null; a --- 1 2 3 4 5 (5 rows) seaboxsql=# select * from subquery_test1 where a!=some(select a from subquery_test2 ) and a is not null; a ---- 1 2 3 4 5 6 7 8 9 10 (10 rows) seaboxsql=# select * from subquery_test1 where a=some(select a from subquery_test2 ); a --- 1 2 3 4 5 (5 rows) seaboxsql=# select * from subquery_test1 where a!=some(select a from subquery_test2 ); a ---- 1 2 3 4 5 6 7 8 9 10 (10 rows) seaboxsql=# select * from subquery_test1 where a=any(select a from subquery_test2 ); a --- 1 2 3 4 5 (5 rows) seaboxsql=# select * from subquery_test1 where a!=any(select a from subquery_test2 ); a ---- 1 2 3 4 5 6 7 8 9 10 (10 rows) seaboxsql=# select * from subquery_test1 where a>any(select a from subquery_test2 ); a ---- 2 3 4 5 6 7 8 9 10 (9 rows) seaboxsql=# select * from subquery_test1 where a<any(select a from subquery_test2 ); a --- 1 2 3 4 (4 rows)
ALL
¶
- 语法
expression operator ALL (subquery)
,row_constructor operator ALL (subquery)
- 描述
-
expression
形式的右手边是一个圆括弧括起来的子查询, 它必须只返回一列。左手边表达式将被计算并使用给出的操作符
对子查询结果逐行进行比较。该操作符必须生成布尔结果。如果所有行得到真(包括子查询没有返回任何行的情况),ALL
的结果就是“真”。如果没有存在任何假值结果,那么结果是“假”。如果比较为任何行都不返回假并且对至少一行返回NULL,则结果为 NULL。row_constructor
形式的左手边是一个行构造器,右手边是一个圆括弧括起来的子查询,它必须返回和左手边行中表达式一样多的列。 左手边表达式将被计算并使用给出的操作符
对子查询结果逐行进行比较。如果对所有子查询行该比较都返回真,那么ALL
的结果就是“真”(包括子查询没有返回任何行的情况)。如果对任何子查询行比较返回假,则结果为“假”。如果比较对任何子查询行都不返回假并且对至少一行返回NULL,则结果为 NULL。NOT IN
等价于<> ALL
。 - 示例
-
注意以下例子中的不同操作符的表现。
seaboxsql=# select * from subquery_test1 where a=all(select a from subquery_test2); a --- (0 rows) seaboxsql=# select * from subquery_test1 where a=all(select a from subquery_test2 where a is not null); a --- (0 rows) seaboxsql=# select * from subquery_test1 where a!=all(select a from subquery_test2); a --- (0 rows) seaboxsql=# select * from subquery_test1 where a!=all(select a from subquery_test2 where a is not null); a ---- 6 7 8 9 10 (5 rows) seaboxsql=# select * from subquery_test1 where a>all(select a from subquery_test2 ); a --- (0 rows) seaboxsql=# select * from subquery_test1 where a>all(select a from subquery_test2 where a is not null); a ---- 6 7 8 9 10 (5 rows)