同じような複数のテーブルを縦に重ねたような「テーブル」が欲しいという場合は、コピーペーストや追加クエリにより実現できます。
では、もともとのテーブルに手を加えることなく、各テーブルのレコードを縦に重ねたような「クエリ」が欲しいという場合はどうしたらいいでしょうか。簡単にできそうな気がしますが実は案外厄介で、通常のクエリのデザインビューの操作では実現できません。そこでユニオンクエリというものを使います。
しかし機能的には単なる「空白のSQLビュー」に過ぎません。必要となるSQLをユーザーが直接入力しなければなりませんので、初心者には少々敷居が高いものとなっています。ただし、下記の備考で触れているように、選択クエリのSQLを転用することで作成の負担を軽減することもできます。
手順
単純な例
サンプルとして2つのテーブルを用います。このテーブルと…
このテーブルです。テーブルのつくりは全く同じものとなっています。
この2つのテーブルを縦に重ねたようなクエリを作ってみます。
クエリのデザインビューです。
テーブルを置かず、空白の状態のままウインドウ条文の「ユニオン」というメニューをクリックします。
現れるのは空白のSQLビューです。
そこで次のように入力します。
入力してからクエリを保存するとクエリのアイコンが変化します。
SELECT * FROM 茶道部員テーブル UNION SELECT * FROM 能楽部員テーブル;
一応補足ですが「SELECT * FROM 茶道部員テーブル」により茶道部員テーブルのすべての列が抽出されます。「SELECT * FROM 能楽部員テーブル」も同様です。
この2つのSELECT文の間に「UNION」があることにより、2つのSELECT文の結果を縦に重ねたクエリを得ることができます。
なお、ユニオンクエリではデザインビューに移る(戻る)ことはできません。
データシートビューです。2つのテーブルのデータが縦に重なって出力されています。
ただし、2つのテーブルのレコードが混在する形になっていることに注意してください。元のテーブルを区別するような列がなく、特に並び順も指定していませんのでこのような結果となっています。もとのテーブルごとに分けて並べたい場合は下記の例(その2)を参考としてください。
応用例
その1
さて、次にちょっとした応用例です。
用いるのはこのテーブルと…
このテーブルです。
上記の例と異なるのは次の2点です。
・茶道部員テーブルに「住所」列があり、2つのテーブルの列数が異なる
・電話番号を記録する列が、茶道部員テーブルでは「TEL」列、能楽部員テーブルでは「電話」列となっている
そこで、ここでは次のようなユニオンクエリを作成するものとします。
・「住所」列は抽出しない
・電話番号を記録している列を抽出し、名前を「電話番号」列とする
「ユニオン」に進んだ画面です。
次のように入力します。
SELECT 学生番号,氏名,TEL AS 電話番号 FROM 茶道部員テーブル UNION SELECT 学生番号,氏名,電話 FROM 能楽部員テーブル;
抽出する列名を直接指定することで住所列を抽出の対象から除き、各テーブルから3つの列を抽出しています(2つのテーブルの列数が異なるため、上記の例のように「*」を用いるとエラーとなってしまいます)。
また、「TEL AS 電話番号」によりTEL列の列名を「電話番号」に変更しています。ユニオンクエリの列名は最初のSELECT文で決めた列名に従いますので、2つ目のテーブルで「AS~」と繰り返し指定する必要はありません。ただし列の指定の順番を間違えないよう注意してください。
データシートビューです。
その2
さて最後の例です。
用いるテーブルは1つ上の例(その1)と同じとし、次のようなユニオンクエリを作成するものとします。
・茶道部テーブルから抽出したレコードを上に並べ、能楽部テーブルからのレコードは下に並べる。同じ部のレコードについては「学生番号」の順にする
・「住所」列を抽出する。能楽部員テーブルには「住所」列がないので、同テーブルから抽出されるレコードについては「住所」列の値をNullとする
・電話番号を記録している列を抽出し、名前を「電話番号」列とする(その1と同じ)
「ユニオン」に進んだ画面です。
次のように入力します。
SELECT 学生番号,氏名,住所,TEL AS 電話番号,1 AS 部番号 FROM 茶道部員テーブル UNION SELECT 学生番号,氏名,Null,電話,2 FROM 能楽部員テーブル ORDER BY 部番号, 学生番号;
補足ですが「1 AS 部番号 FROM 茶道部員テーブル」の部分により「部番号」という列が設けられ、茶道部員テーブルから抽出されたレコードについては値が「1」となります。2行目の「2 FROM 能楽部員テーブル」により、能楽部員テーブルから抽出されたレコードについては値が「2」となります。3行目の「ORDER BY 部番号, 学生番号」により、この2つの列をキーとする並べ替えが行われます。ORDER BYはこのように最後に置く必要があります。
能楽部員テーブルには住所列がありませんので、2行目で値を「Null」と直接指定しています。
データシートビューです。
備考
「ユニオン」というメニューとして存在するにもかかわらず具体的な支援機能が一切なく、SQLを直接入力しないと実現できません。実際のところ選択クエリのSQLビューにSQLを入力しても同じ結果になります;-o-)ただしSQLを入力すればどのメニューからでも実現できるという点は各種アクションクエリなども同じです。
その他、いくつか重要なポイントを記しておきます。
簡単な作成方法
UNIONでつなぐ個々のSELECT文を選択クエリにより作成し、あとは「それぞれのクエリのSQLビューからSQLをコピペし『UNION』でつなぐ」ことにより比較的簡単に作成できます。個々のSELECT文が複雑になる場合は特に有効です。
3つ以上のテーブルによるユニオンクエリ
これは単純で、必要なだけSELECT文とUNIONを繰り返せばOKです。
つまり次のようなSQLになります。
SELECT ~ FROM~ UNION SELECT ~ FROM~ UNION SELECT ~ FROM~ UNION SELECT ~ FROM~ ・・・
重複行の除外と許容
ユニオンクエリの実行結果として同一のレコードが複数存在する場合、重複が除外され1つのレコードだけが残ります。
同一レコードの重複を除外しないようにするには「UNION」の代わりに「UNION ALL」とします。