SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...]
UNION
は、結果を複数
SELECT
ステートメントから単一結果セットに結合させるために利用されます。
最初の
SELECT
ステートメントからのカラム名は、返された結果のカラム名として利用されます。各
SELECT
ステートメントの対応する位置にリストされている選択されたカラムは、同じデータ型を持つ必要があります。(たとえば、最初のステートメントに選択された最初のカラムは、別のステートメントに選択された最初のカラムと同じ型を持つ必要があります)。
もし、対応する
SELECT
カラムのデータ型が一致しなければ、UNION
結果内の型とカラムの長さは、すべての
SELECT
ステートメントによって検索された値を考慮する必要があります。たとえば、次のものを検討してみてください。
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a |
| bbbbbbbbbb |
+---------------+
(MySQL の初期のバージョンでは、最初の
SELECT
の型と長さだけが利用され、2 つめの行は長さ
1 まで切り捨てられていました)。
SELECT
ステートメントは通常の選択ステートメントですが、次の制約があります。
最後の
SELECT
ステートメントだけが
INTO OUTFILE
を利用できます。(ただし、UNION
の結果全体がファイルに書き込まれます。)
HIGH_PRIORITY
は、UNION
の一部である
SELECT
ステートメントと一緒には利用できません。もしそれを最初の
SELECT
に指定しても、効果はありません。もしそれを後に続く
SELECT
ステートメントに指定すると、構文エラーが起こります。
UNION
のデフォルトの動作は、複製行は結果から削除されるということです。任意の
DISTINCT
キーワードは、複製行の削除の指定もするので、デフォルト以外に何も効果は持ちません。任意の
ALL
キーワードを利用すると、複製行の削除は行われず、結果にはすべての
SELECT
ステートメントからの一致する行が含まれます。
UNION
ALL
と
UNION
DISTINCT
を同じクエリーの中で混合することができます。混合された
UNION
型は
DISTINCT
ユニオンがすべての
ALL
ユニオンをその左側に上乗せするような形で扱われます。DISTINCT
ユニオンは
UNION
DISTINCT
を利用して明示的に、またあとに
DISTINCT
や
ALL
キーワードがない
UNION
を利用して暗黙的に作成されます。
ORDER BY
や
LIMIT
節を、UNION
結果全体をソートしたり制限したりするために利用するには、各
SELECT
ステートメントを括弧で囲み、最後のものの後に
ORDER BY
か
LIMIT
を置いてください。次の例は、両方の節を利用しています。
(SELECT a FROM t1 WHERE a=10 AND B=1) UNION (SELECT a FROM t2 WHERE a=11 AND B=2) ORDER BY a LIMIT 10;
この種の ORDER BY
はテーブル名を含むカラム参照を利用することができません。(それは、tbl_name
.col_name
フォーマット内の名前です)。その代わりに、最初の
SELECT
ステートメント内でカラムエイリアスを提供し、ORDER
BY
内でそのエイリアスを参照します。(あるいは、そのカラムの位置を利用して
ORDER BY
内でカラムを参照します。しかし、カラム位置の使用は今後廃止予定です)。
また、もし格納されるカラムがエイリアスされると、ORDER
BY
節は、カラム名ではなく、そのエイリアスを参照
しなければいけません。次のステートメントの
1 つめのものは機能しますが、2 つめは
Unknown column 'a' in 'order
clause'
エラーで失敗します。
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b; (SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
個々の SELECT
に
ORDER BY
か
LIMIT
を適用するには、SELECT
を囲む括弧内に節を置いてください。
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
ただし、デフォルトでは
UNION
は順序付けられていない行のセットを生成するため、個々の
SELECT
ステートメントに対して
ORDER BY
を使用しても、最終結果で行が現れる順序には何も影響を及ぼしません。そのため、このコンテキストでは通常、ORDER
BY
は LIMIT
と組み合わせて使用されます。それにより、選択された行の
UNION
の最終結果での順序に必ずしも影響を与えるわけではないにもかかわらず、SELECT
で取り出すためのこれらの行のサブセットを決定するために使用されるようになります。
もし ORDER BY
が
SELECT
内に
LIMIT
なしで現れても、何の効果も持たないため最適化されて切り離されます。
UNION
の結果内の行が、各
SELECT
によって 1
つずつ検索された行で構成されるようにするためには、各
SELECT
からソートカラムとして利用するための追加カラムを選択し、最後の
SELECT
の後に
ORDER BY
を追加してください。
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
さらに、個々の
SELECT
の結果の中でソートの順番を維持するためには、ORDER
BY
節に補助的なカラムを追加してください。
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
また、追加のカラムを使用することによって、各行がどの
SELECT
から得られるかも決定できるようになります。追加のカラムでは、テーブル名を示す文字列などのほかの識別情報も指定できます。