Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 12.0.1 » SQL Anywhere サーバー SQL の使用法 » データの問い合わせと修正 » クエリ結果の要約、グループ化、ソート » UNION、INTERSECT、EXCEPT を使用した、クエリ結果に対する集合操作

 

集合演算子と NULL

集合演算子 UNION、EXCEPT、INTERSECT と探索条件内では、NULL を扱う方法が異なります。この違いが、集合演算子を使用する主な理由の 1 つです。

ローを比較するとき、集合演算子は、NULL 値を互いに等しいものとして扱います。対照的に、探索条件で NULL が NULL と比較された場合、結果は不定 (真ではない) となります。

この違いがもたらす結果の 1 つとして、query-1 EXCEPT ALL query-2 の結果セット内のロー数が、常に各クエリの結果セット内のロー数の差異であるということです。

テーブル T1 と T2 を例に説明します。各テーブルには、次のカラムがあります。

col1 INT,
col2 CHAR(1)

テーブルとデータは次のように設定されています。



CREATE TABLE T1 (col1 INT, col2 CHAR(1));
CREATE TABLE T2 (col1 INT, col2 CHAR(1));
INSERT INTO T1 (col1, col2) VALUES(1, 'a');
INSERT INTO T1 (col1, col2) VALUES(2, 'b');
INSERT INTO T1 (col1) VALUES(3);
INSERT INTO T1 (col1) VALUES(3);
INSERT INTO T1 (col1) VALUES(4);
INSERT INTO T1 (col1) VALUES(4);
INSERT INTO T2 (col1, col2) VALUES(1, 'a');
INSERT INTO T2 (col1, col2) VALUES(2, 'x');
INSERT INTO T2 (col1) VALUES(3);

テーブル内のデータは次のようになっています。

  • テーブル T1

    col1 col2
    1 a
    2 b
    3 (NULL)
    3 (NULL)
    4 (NULL)
    4 (NULL)
  • テーブル T2

    col1 col2
    1 a
    2 x
    3 (NULL)

T2 にもある T1 のローを要求するクエリの一例を次に示します。

SELECT T1.col1, T1.col2
   FROM T1 JOIN T2
   ON T1.col1 = T2.col1
   AND T1.col2 = T2.col2;
T1.col1 T1.col2
1 a

ロー (3, NULL) は、結果セットにありません。これは、NULL と NULL の比較が真ではないためです。対照的に、INTERSECT 演算子を使用してこの問題にアプローチすると、結果に NULL を持つローが含まれます。

SELECT col1, col2
   FROM T1
   INTERSECT
      SELECT col1, col2
         FROM T2;
col1 col2
1 a
3 (NULL)

次のクエリは、探索条件を使用して T2 にはない T1 のローをリストしています。



SELECT col1, col2
   FROM T1
   WHERE col1 NOT IN (
       SELECT col1
         FROM T2
         WHERE T1.col2 = T2.col2 )
   OR col2 NOT IN (
       SELECT col2
         FROM T2
         WHERE T1.col1 = T2.col1 );
col1 col2
2 b
3 (NULL)
4 (NULL)
3 (NULL)
4 (NULL)

T1 の NULL を含むローは、比較によって除外されていません。対照的に、EXCEPT ALL を使用してこの問題にアプローチすると、両方のテーブルに含まれる NULL を持つローが結果から除外されます。この場合、T2 の (3, NULL) ローは、T1 の (3, NULL) ローと同じと認識されています。

SELECT col1, col2
   FROM T1
   EXCEPT ALL
      SELECT col1, col2
         FROM T2;
col1 col2
2 b
3 (NULL)
4 (NULL)
4 (NULL)

EXCEPT 演算子を使用すると、結果がさらに制限されます。EXCEPT 演算子は、T1 から (3, NULL) のローを両方とも削除し、また (4, NULL) ローの 1 つを重複として除外しています。

SELECT col1, col2
   FROM T1
   EXCEPT
      SELECT col1, col2
         FROM T2;
col1 col2
2 b
4 (NULL)