16.20 - 例: SELECT文の順序がデータ型に及ぼす影響 - Teradata Database - Teradata Vantage NewSQL Engine

Teradata Vantage™ SQLデータ操作言語

Product
Teradata Database
Teradata Vantage NewSQL Engine
Release Number
16.20
Release Date
2019年3月
Content Type
プログラミング リファレンス
Publication ID
B035-1146-162K-JPN
Language
日本語 (日本)

UNIONの結果は常に、最初のSELECTの選択値のデータ型を使って表現されます。これはつまり、SELECT A UNION SELECT B は必ずしも、SELECT B UNION SELECT A と同じ結果を戻すとは限らないということです。ただし、どちらのケースでも同じ結果が戻されるよう、明示的に出力データ型を変換する場合は別です。

次の複雑な UNION を使った問合わせについて考えてみましょう。

   SELECT MIN(X8.i1)
   FROM t8 X8
   LEFT JOIN t1 X1 ON X8.i1=X1.i1
   AND X8.i1 IN
   (SELECT COUNT(*) 
   FROM t8 X8
   LEFT JOIN t1 X1 ON X8.i1=X1.i1
   AND X8.i1 = ANY
   (SELECT COUNT(*)
   FROM t7 X7
   WHERE X7.i1 = ANY
   (SELECT AVG(X1.i1)
   FROM t1 X1)))
   UNION
   SELECT AVG(X4.i1)
   FROM t4 X4
   WHERE X4.i1 = ANY
   (SELECT (X8.i1)
   FROM t1 X1
   RIGHT JOIN t8 X8 ON X8.i1=X1.i1
   AND X8.i1 = IN
   (SELECT MAX(X8.i1)
   FROM t8 X8
   LEFT JOIN t1 X1 ON X8.i1=X1.i1
   AND
   (SELECT (X4.i1)
   FROM t6 X6
   RIGHT JOIN t4 X4 ON X6.i1=i1))));
   

結果は以下のように報告されます。

   Minimum(i1)
   -----------
            -2
             0

直感的には、UNIONの両側の問合わせの順序を入れ替えても、同じ結果を生成するはずだと思えるかもしれません。最初のSELECTの選択値のデータ型が異なる場合があるので、必ずしもそのようにはなりません。同じデータベースにおける次の問合わせがそのことを例示しています。

   SELECT AVG(X4.i1)
   FROM t4 X4
   WHERE X4.i1 = ANY
   (SELECT (X8.i1)
   FROM t1 X1
   RIGHT JOIN t8 X8 ON X8.i1 = X1.i1
   AND X8.i1 = ANY
   (SELECT MAX(X8.i1)
   FROM t8 X8
   LEFT JOIN t1 X1 ON X8.i1 = X1.i1
   AND
   (SELECT (X4.i1)
   FROM t6 X6
   RIGHT JOIN t4 X4 ON X6.i1 = i
   )
   )
   )
   UNION
   SELECT MIN(X8.i1)
   FROM t8 X8
   LEFT JOIN t1 X1 ON X8.i1 = X1.i1
   AND X8.i1 IN
   (SELECT COUNT(*) 
   FROM t8 X8
   LEFT JOIN t1 X1 ON X8.i1 = X1.i1
   AND X8.i1 = ANY
   (SELECT COUNT(*)
   FROM t7 X7
   WHERE X7.i1 = ANY
   (SELECT AVG(X1.i1)
   FROM t1 X1
   )
   );

結果は以下のように報告されます。

   Average(i1)
   -----------
            -2
             1

実際の平均は< 0.5 です。UNIONの中のSELECTの順序を逆にすると違いが生じるのはなぜでしょうか?一見矛盾した結果が生じる理由が、次のテーブルに説明されています。

最初のSELECTが指定する関数 結果のデータ型 結果として戻される値
AVG REAL 1
MIN INTEGER 0に切り捨てられる