SQL学びその10 テーブルごとの集合演算

SQL学びその10 テーブルごとの集合演算

最初、驟雨豪円山となってそんな地名あるのかと思ったらなかった。驟雨ということばはあるのね。

さて、最後。テーブルごとの集合演算。3パターンある。

和集合 2つのテーブルの重複した行も重複したまま(か重複を1つと数えて)追加し、それ以外も表に追加する集合
123 と345のテーブルなら123345となる
123と345のテーブルなら12345とするつくり方もある

積集合 2つのテーブルの重複した行のみを追加する集合
123と345のテーブルなら3となる。

差集合 片方のテーブルからもう片方のテーブルに乗っている重複したしていないものだけを残す集合
123と345のテーブルなら12となる。

和集合 UNIONの使い方

SELECT 列の指定 FROM 1つ目のテーブル
UNION ALL | DISTINCT
SELECT 列の指定 FROM 2つ目のテーブル
UNION ALL | DISTINCT
SELECT 列の指定 FROM 3つ目のテーブル
;

() 括弧をつかって順番を決めることもできる。
(SELECT 列の指定 FROM 1つ目のテーブル
UNION ALL
SELECT 列の指定 FROM 2つ目のテーブル)
UNION ALL | DISTINCT
SELECT 列の指定 FROM 3つ目のテーブル
;

とか。

UNIONの注意点

  1. UNIONする2つのテーブルは同じ列数でなければならない
  2. 列名ではなく順序で集合演算するので順番も同じじゃないと変になる
  3. 和集合をつくるテーブルの列数順序が同じなら SELECT *でもいい
  4. UNIONで生成するテーブルの列名は1つ目のテーブルの列名が利用される
  5. 重複を気にしない場合はUNION ALLをつかう。この場合は1つ目のテーブルの行数と2つ目のテーブルの行数の合計が生成したテーブルの行数になる
  6. 重複を気にする場合はUNION DISTINCTをつかう。この場合1つ目のテーブルの行数ー2つ目のテーブルの行数ー重複したテーブルの行数が生成したテーブルの行数になる
  7. すべての列の値が一致した場合に重複したデータとみなされる。名前が同じでも日時が違うと違うデータになるね。

ちなみにWHERE句で絞り込みをしたいときに、注意したいのか書いた直前のSELECT文しか聞かない。全部に対して絞り込みたかったらサブクエリ使おう。学んだよね。
SELECT
*
FROM
(
SELECT 列の指定 FROM 1つ目のテーブル
UNION ALL | DISTINCT
SELECT 列の指定 FROM 2つ目のテーブル
UNION ALL | DISTINCT
SELECT 列の指定 FROM 3つ目のテーブル
)
WHERE 絞り込みたい列= ‘絞り込みたい内容’
;

とかね。

積集合 INTERSECTの使い方

SELECT 列の指定 FROM 1つ目のテーブル
INTERSECT DISTINCT
SELECT 列の指定 FROM 2つ目のテーブル
INTERSECT DISTINCT
SELECT 列の指定 FROM 3つ目のテーブル
;

DISTINCT絶対必要。ないとエラーになる。

  1. INTERSECTする2つのテーブルは同じ列数でなければならない
  2. 列名ではなく順序で集合演算するので順番も同じじゃないと変になる
  3. INTERSECTで生成するテーブルの列名は1つ目のテーブルの列名が利用される
  4. すべての列の値が一致した場合に重複したデータとみなされる。

ここで3つのテーブルに2つ以上列に完全一致で重複して入ってるデータを取り出すなら

(SELECT 列 FROM テーブルA
UNION DISTINCT
SELECT 列 FROM テーブルB)
INTERSECT DISTINCT
SELECT 列 FROM テーブルC
;

なんて書き方で出てくる。こういうところ、頭の良さが出るなと思う。私は

(SELECT 列 FROM テーブルA
INTERSECT DISTINCT
SELECT 列 FROM テーブルB)
UNION DISTINCT
(SELECT 列 FROM テーブルB
INTERSECT DISTINCT
SELECT 列 FROM テーブルC)
UNION DISTINCT
(SELECT 列 FROM テーブルA
INTERSECT DISTINCT
SELECT 列 FROM テーブルC)
;

って書いてしまった。同じ結果だけど前述のほうがずっとシンプル。わかるかな?

差集合 EXCEPTの使い方

SELECT 列 FROM 左側のテーブル
EXCEPT DISTINCT
SELECT 列 FROM 右側のテーブル

右左が大事。ほかは他の参考にすれば注意点はわかるかな。
さっきまではどっちにおいても変わらないけど、
この場合右左によって結果は変わる。