★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

9.24. 行と配列の比較

本節では、値のグループ間で複数の比較を行う、さまざまな特殊化したコンストラクトについて説明します。 この形式は構文的には、前節の副問い合わせ形式と関係しています。しかし、副問い合わせを含みません。 配列副式を含む形式はPostgreSQLの拡張ですが、それ以外はSQL準拠です。 本節で記載した全ての式形式は結果として論理値(真/偽)を返します。

9.24.1. IN

expression IN (value [, ...])

右辺は括弧で括られたスカラ式のリストです。 左辺の式の結果が右辺の式のいずれかと等しい場合、結果はtrue(真)になります。 これは以下の省略形です。

expression = value1
OR
expression = value2
OR
...

左辺の式がNULLを生じる場合、または右側の値に等しいものがなくて少なくとも1つの右辺の行がNULLを持つ場合、IN構文の結果は偽ではなくNULLとなることに注意してください。 これは、NULL値の論理的な組み合わせに対するSQLの標準規則に従うものです。

9.24.2. NOT IN

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

右辺は括弧で括られたスカラ式のリストです。 左辺の式の結果が右辺の式の全てと等しくない場合、結果はです。 これは以下の省略形です。

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

左辺の式でNULLが生じる場合、または右辺の値に左辺の式と等しいものがなく、かつ少なくとも1つの右辺の式がNULLを生じる場合、NOT IN構文の結果は、一部の人が予想する真ではなく、NULLとなることに注意してください。 これは、NULL値の論理的な組み合わせに対するSQLの標準規則に従うものです。

ヒント

全ての場合において、x NOT IN yNOT (x IN y)と等価です。 しかし、INを使用するよりもNOT INを使用する方が初心者がNULL値による間違いをしやすくなります。 可能な限り条件を肯定的に表現することが最善です。

9.24.3. ANY/SOME (配列)

expression operator ANY (array expression)
expression operator SOME (array expression)

右辺は括弧で括られた式で、配列値を返さなければなりません。 左辺の式は配列要素それぞれに対して、指定されたoperatorを使用して評価、比較されます。なお、operatorは結果として論理値を生成する必要があります。 真の結果が1つでもあると、ANYの結果はtrue(真)です。 真の結果がない(配列の要素数がゼロである場合を含む)と、結果はfalse(偽)です。

配列式がNULL配列を生成する場合、ANYの結果はNULLになります。 左辺式がNULLとなる場合、ANYの結果は通常NULLになります(STRICTでない比較演算子では異なる結果になるかもしれません)。 また、右辺の配列にNULL要素が含まれ、かつ、比較の結果、真が得られなかった場合、ANYの結果は偽ではなくNULLになります(ここでも、STRICTな演算子の場合です)。 これは、NULLに対する、SQLの論理値組み合わせに関する標準規則に従うものです。

SOMEANYの同義語です。

9.24.4. ALL (配列)

expression operator ALL (array expression)

右辺は括弧で括られた式で、配列値を返さなければなりません。 左辺の式は配列の要素それぞれに対して、指定されたoperatorを使用して評価、比較されます。なお、operatorは結果として論理値を生成する必要があります。 全ての比較が真になる場合(配列の要素数がゼロである場合を含む)、ALLの結果はtrue(真)です。 1つでも偽の結果があると、結果はfalse(偽)です。

配列式がNULL配列を生成する場合、ALLの結果はNULLになります。 左辺式がNULLとなる場合、ALLの結果は通常NULLになります(厳格でない比較演算子では異なる結果になるかもしれません)。 また、右辺の配列にNULL要素が含まれ、かつ、比較の結果、偽が得られなかった場合、ALLの結果は真ではなくNULLになります(ここでも、厳格な演算子の場合です)。 これは、NULLに対する、SQLの論理値組み合わせに関する標準規則に従うものです。

9.24.5. 行コンストラクタの比較

row_constructor operator row_constructor

両辺とも4.2.13で説明する行コンストラクタです。 この2つの行値は同じフィールド数でなければなりません。 両辺はそれぞれ評価され、行として比較されます。 行コンストラクタの比較は、operator=<><<=>>=の場合に認められます。 各行の要素はデフォルトのB-tree演算子クラスを持つ型でなければなりません。そうでなければ、比較を試みるとエラーが発生します。

注記

比較が先行する列で解決された場合、要素の数や型に関係するエラーは起きないこともあります。

=<>の場合、他と動作が多少異なります。 2つの行は対応する全ての構成要素が非NULLかつ等しい場合に等しいとみなされます。 1つでも構成要素が非NULLかつ等しくない場合、2つの行は等しくないとみなされます。 それ以外の場合、その行の比較結果は不明(NULL)です。

<<=>>=の場合、行の要素は左から右に比較されます。そして、不等またはNULLの組み合わせが見つかったところで停止します。 要素の組み合わせのどちらかがNULLであった場合、行比較の結果は不明(NULL)です。さもなくば、要素の組み合わせの比較により結果が決まります。 例えば、ROW(1,2,NULL) < ROW(1,3,0)は、3番目の要素の組み合わせまで進まないため、NULLではなく真を返します。

注記

PostgreSQLの8.2より前では、<<=>>=の場合SQL仕様に従っていませんでした。 ROW(a,b) < ROW(c,d)などの比較は正しくはa < c OR (a = c AND b < d)ですが、a < c AND b < dとして実装されていました。

row_constructor IS DISTINCT FROM row_constructor

このコンストラクトは<>行比較と類似していますが、NULL入力に対してNULLを生成しない点が異なります。 その代わりに、全てのNULL値は非NULL値と等しくない(DISTINCT FROM)ものとみなされ、また、2つのNULLは等しい(NOT DISTINCT)ものとみなされます。 したがって、結果は真か偽のいずれかで、NULLにはなりません。

row_constructor IS NOT DISTINCT FROM row_constructor

このコンストラクトは=行比較と類似していますが、NULL入力に対してNULLを生成しません。 代わりに、NULL値を、すべての非NULLの値に対して不等(DISTINCT FROM)とみなし、2つのNULLを等しいもの(NOT DISTINCT)とみなします。 したがって、結果は常に真か偽となり、NULLになることはありません

9.24.6. 複合型の比較

record operator record

SQL仕様では、結果が2つのNULL値、またはNULLと非NULLの比較に依存するのであれば、行の観点からの比較はNULLを返すことを要求されています。 PostgreSQLは、(9.24.5にあるように)2つの行コンストラクタの出力の比較を行う時、または副問い合わせの出力に対し(9.23にあるように)行コンストラクタの比較を行う時のみこれを実施します。 2つの複合型の値が比較されるほかの状況では、2つのNULLフィールドの値は等しいと考えられ、NULLは非NULLより大きいとみなされます。 複合型に対して、これは一貫した並び替えとインデックス付け動作担保のため必要です。

各辺が評価され、行単位で比較が行なわれます。 複合型の比較はoperator=<><<=>>=またはそのいずれかと類似の意味を持つ場合に許されます。 (正確には、演算子はB-tree演算子クラスのメンバである場合、またはB-tree演算子クラスの=メンバの否定子である場合に行比較演算子となり得ます。) 上記の演算子のデフォルトの動作は、行コンストラクタに対するIS [ NOT ] DISTINCT FROMと同じです(9.24.5参照)。

デフォルトのB-tree演算子クラスを持たない要素を含む行の一致をサポートするために、いくつかの演算子が複合型の比較のために定義されています。 それは*=*<>*<*<=*>*>=です。 上記の演算子は2つの行の内部バイナリ表現を比較します。 2つの行の等価演算子での比較が真であっても、2つの行はバイナリ表現が異なるかもしれません。 上記の比較演算子での行の順序は決定論的ですが、それ以外は意味がありません。 上記の演算子はマテリアライズドビューで内部的に使われ、レプリケーションやB-Treeの重複除去(63.4.2参照)のような他の特定の目的のためには有用かもしれませんが、問い合わせを書くのに一般的に有用であるようには意図していません。