■ はじめに
https://dk521123.hatenablog.com/entry/2023/01/16/000000
で、SQLは、集合演算だと説明した。 今回は、集合演算の足し算を表す SQLの UNION / UNION ALL について、学ぶ。
目次
【1】 UNION 1)構文 2)サンプル 【2】 UNION ALL 1)構文 2)サンプル 3) 補足:UNION ALL の 使い方 【3】 Union と Union All の違い 1)サンプル 2)まとめ 【4】 使用上の注意
【1】 UNION
* レコードを足し合わせる機能 * 1つの条件 + 別の条件を繋げる時(和集合の実現)に役立つ
※ 和集合とは...
* 2つの集合A, Bに対して、どちらの要素にも入る
SQL ~ 関係演算 / 集合論 ~
https://dk521123.hatenablog.com/entry/2023/01/16/000000
1)構文
SELECT [item name1] FROM [table name1] UNION SELECT [item name2] FROM [table name2]
2)サンプル
SELECT u.user_name AS name FROM users AS u UNION SELECT e.emp_name AS name FROM employee AS e;
【2】 UNION ALL
* Union で重複含む版
1)構文
SELECT [item name1] FROM [table name1] UNION ALL SELECT [item name2] FROM [table name2]
2)サンプル
例1:簡単なデータ
SELECT u.user_name AS name FROM users AS u UNION ALL SELECT e.emp_name AS name FROM employee AS e;
例2:重複ユーザを排除した結果を表示
-- 1-1)昨日のデータ格納用テーブル CREATE TABLE "user_20200615" ( "id" INT NOT NULL, "name" TEXT NULL DEFAULT NULL, PRIMARY KEY ("id") ); -- 1-2)今日のデータ格納用テーブル(1-1)と同等のテーブル) CREATE TABLE "user_20200616" ( "id" INT NOT NULL, "name" TEXT NULL DEFAULT NULL, PRIMARY KEY ("id") ); -- 2)サンプルデータ INSERT INTO user_20200615 VALUES(1, 'Mike'),(2, 'Smith'); INSERT INTO user_20200616 VALUES(2, 'Smith'),(3, 'Tom'); -- 3)重複ユーザを排除した結果を表示(★今回のテーマ★) -- 今日データ SELECT main.id, main.name FROM user_20200616 AS main UNION ALL -- 昨日データ -- => 昨日データだけ欲しいので、LEFT OUTER JOINで結合した結果に対して -- 「WHERE new.id IS NULL」今日データが含まれているデータを省く SELECT old.id, old.name FROM user_20200615 AS old LEFT OUTER JOIN user_20200616 AS new ON old.id = new.id WHERE new.id IS NULL ORDER BY id -- 出力結果は以下の通り(重複データ「2 Smith」がまとまって表示)
id | name |
---|---|
1 | Mike |
2 | Smith |
3 | Tom |
3) 補足:UNION ALL の 使い方
* リポートとしても使える
サンプル
SELECT 1 AS no, 'data count' AS item, (SELECT COUNT(u.user_id) FROM users AS u) AS value UNION ALL SELECT 2 AS no, 'max id' AS item, (SELECT MAX(u.user_id) FROM users AS u) AS value UNION ALL SELECT 3 AS no, 'min id' AS item, (SELECT MIN(u.user_id) FROM users AS u) AS value
出力結果例
no | item | value |
---|---|---|
1 | data count | 6 |
2 | max id | 6 |
3 | min id | 1 |
【3】 Union と Union All の違い
Union
* DISTINCT(重複を統合)のような形で結果を返す * 集合だと 「A + B - (A^B; AとBの共通部分)」
Union All
* 重複も含めて、全ての結果を返す * 集合だと A + B
1)サンプル
データ準備
CREATE TABLE member_old ( id INT, name VARCHAR(50), gender VARCHAR(1), country_code VARCHAR(3), class VARCHAR(10), updated_date DATE ); CREATE TABLE member_new ( id INT, name VARCHAR(50), gender VARCHAR(1), country_code VARCHAR(3), class VARCHAR(10), updated_date DATE ); -- INSERT member_old INSERT INTO member_old (id,name,gender,country_code,class,updated_date) VALUES (1,'Mike','m','USA','bronze','2024-09-14'), (2,'Tom',NULL,'GBR','gold','2024-09-14'), (3,'Smith','f',NULL,'silver','2024-09-14'), (4,'Ken',NULL,'JPN','gold','2024-09-14'), (5,'Jack','m','UKR','gold','2024-09-14') ; -- INSERT member_new INSERT INTO member_new (id,name,gender,country_code,class,updated_date) VALUES (1,'Mike','m','USA','bronze','2024-09-14'), (2,'Tom','m','GBR','platinum','2024-09-15'), -- ★変更 (3,'Smith','f',NULL,'silver','2024-09-14'), (4,'Ken','m','JPN','gold','2024-09-15'), -- ★変更 (5,'Jack','m','UKR','gold','2024-09-14'), (6,'Henry','m','AUS','silver','2024-09-15') -- ★追加 ;
UNION の場合
SELECT * FROM member_old UNION SELECT * FROM member_new ORDER BY id; -- => 重複削除されている(例えば、id = 1 が1つだけ表示)
id | name | gender | country_code | class | updated_date |
---|---|---|---|---|---|
1 | Mike | m | USA | bronze | 2024-09-14 |
2 | Tom | m | GBR | platinum | 2024-09-15 |
2 | Tom | GBR | gold | 2024-09-14 | |
3 | Smith | f | silver | 2024-09-14 | |
4 | Ken | m | JPN | gold | 2024-09-15 |
4 | Ken | JPN | gold | 2024-09-14 | |
5 | Jack | m | UKR | gold | 2024-09-14 |
6 | Henry | m | AUS | silver | 2024-09-15 |
UNION ALL の場合
SELECT * FROM member_old UNION ALL SELECT * FROM member_new ORDER BY id; -- => 重複表示 を表示している(例えば、id = 1 が2重にある)
id | name | gender | country_code | class | updated_date |
---|---|---|---|---|---|
1 | Mike | m | USA | bronze | 2024-09-14 |
1 | Mike | m | USA | bronze | 2024-09-14 |
2 | Tom | m | GBR | platinum | 2024-09-15 |
2 | Tom | GBR | gold | 2024-09-14 | |
3 | Smith | f | silver | 2024-09-14 | |
3 | Smith | f | silver | 2024-09-14 | |
4 | Ken | JPN | gold | 2024-09-14 | |
4 | Ken | m | JPN | gold | 2024-09-15 |
5 | Jack | m | UKR | gold | 2024-09-14 |
5 | Jack | m | UKR | gold | 2024-09-14 |
6 | Henry | m | AUS | silver | 2024-09-15 |
2)まとめ
UNION | UNION ALL | |
---|---|---|
重複行 | 重複削除 | 重複表示 |
【4】 使用上の注意
* ORDER BYを利用する時には、 フィールドを取得しておかなければならない (★これに、はまった★) * 取得するフィールドの数/型が、一致しなければならない (SELECT句のカラム数が同じ) * 以上のことが考慮されていれば、 異なるテーブルであっても問題なし。
参考資料
http://www.atmarkit.co.jp/fnetwork/rensai/sql09/sql1.html
http://www.techscore.com/tech/sql/08_01.html/
サンプルが分かりやすい
http://www.dbonline.jp/mysql/select/index18.html
関連記事
テーブルの結合 ~内部結合・INNER JOIN~
https://dk521123.hatenablog.com/entry/2010/02/05/131206
テーブルの結合 ~外部結合・LEFT OUTER JOIN、RIGHT JOIN~
https://dk521123.hatenablog.com/entry/2012/05/06/212246
テーブルの結合 ~交差結合・CROSS JOIN~
https://dk521123.hatenablog.com/entry/2011/12/21/000000
全く関係ないテーブルを結合することを考える
https://dk521123.hatenablog.com/entry/2021/09/16/185552
SQL ~ 関係演算 / 集合論 ~
https://dk521123.hatenablog.com/entry/2023/01/16/000000