【SQL】unionの使いどころ

結論から言うと

複数のテーブルのフィールドをまとめて出力したい時に、joinが使えない局面で、unionを使う。より具体的に言うと、具象テーブル継承で設計されたテーブル同士をひとつにまとめたい時に使える。

ある日のエピソード

上司「社員とアルバイトの情報をエクセルに出力して欲しいんだけど」
君 「えっと、社員とアルバイトは別シートでよろしいですか?」
上司「いや、社員もアルバイトも同じシートに、ひとつにまとめて出し
   て。いちいちシートを往復したくないのよ」
君 (うーん、どうすればいいんだ?実はウチの基幹システムのテーブル
   の設計があんまり好きじゃないんだよな。確かこんな感じの設計だ
   った・・・。

画像1

基幹システムはずいぶん昔に作られたものらしい。だから、あまりテーブルの設計の指針とかもなかったのだろう。今だったら、次のようなテーブルの設計が一般的なんじゃないかな・・。

画像2

これだったら、きっとjoinを使ったクエリを投げれば全ての社員とアルバイトの両方を合わせた完全なデータが取得できたはずだ。こんな感じで・・・。

select * from
   従業員
       left join 社員 on 従業員.従業員ID = 社員.社員ID
       left join アルバイト on 従業員.従業員ID = アルバイト.アルバイトID

だが、現実問題、これはできない・・・!)

上司「明日までには欲しいな」
君 「え、また急な・・・」
上司「じゃ、よろしく」

さて、どうするか。
そういえば、普段はselectとかjoinとかしか使わないが、リレーショナルデータベースでは、いろいろな操作があった。最近読んだ本では集合の演算が紹介されていた。それが使えないだろうか?そうだ!社員テーブルとアルバイトテーブルの和集合を取れば、上司が欲しがっているエクセルが実現できるのではないか?

SQLで和集合をとるには、unionを使う。
しかし、待てよ、unionを使うには前提条件があった。
・ 列数が同じであること
・同列にある列の型が同じであること

何てこった、列数は同じだけど、型が違うじゃないか。どうすればいい・・。
ええっとクエリを投げる時に無理やり列を追加してしまえば良いのではないか?よく「as」を使って列名を変えたり、計算結果に名前をつけたりしているよな。そうそう「列エイリアス」だっけ。これが使えそうだぞ。
クエリを作成する前にテーブルを確認しよう。

スクリーンショット 2020-05-03 12.11.45

スクリーンショット 2020-05-03 12.12.10

社員テーブルとアルバイトテーブルはこんな感じか。

よし、じゃあ「列エイリアス」を使って、無理やり列を増やしてunionを実行してみよう。

select 社員ID as 従業員ID, 名前, null as シフト区分, ボーナス額 from 社員
union
select アルバイトID, 名前, シフト区分 , 0 as ボーナス額 from アルバイト

スクリーンショット 2020-05-03 12.12.23

よかった、うまくいった。けっこうきれいにできたじゃないか。もし、上司から社員とアルバイトの区別をつけたいと言われたら、また「列エイリアス」を使って、「社員フラグ」という列を追加してやればオーケーだ。

あー、でも、これ、意外と面白い結果になったな。この基幹システムが単一テーブル継承の思想で設計されていたら、まんまこの結果が従業員テーブルになっていたはずだ。RDBって奥が深いんだな・・・。


お気軽にフォローやコメントしてください。けっこう喜びます。