[SQL] UNIONとUNION ALLの違い
今回はSQLの UNION と UNION ALL の違いについて解説する。
どちらも複数の SELECT 結果を統合して1つの結果セットにする演算子だが、挙動とパフォーマンスに大きな違いがある。
結論から言うと、重複排除が必要ない限りは UNION ALL を使うべき である。
準備
本サイトではpythonのライブラリであるsqlite3とipython-sqlを利用して、Jupyter Notebook上でSQLを実行・解説する。 また、データフレームの表示には Polars を利用する。
github
- githubのjupyter notebook形式のファイルはこちら
google colaboratory
- google colaboratory で実行する場合はこちら
筆者の環境
筆者の環境である。
!sw_vers
ProductName: macOS
ProductVersion: 15.5
BuildVersion: 24F74
!python -V
Python 3.12.12
必要なライブラリを読み込む。
import sqlite3
import polars as pl
%load_ext sql
%config SqlMagic.feedback = True
%config SqlMagic.style = '_DEPRECATED_DEFAULT'
データの準備
サンプルとして、2つのクラス ClassA と ClassB の生徒名簿を作成する。
「佐藤さん」は両方のクラスに存在するものとする。
import os
if os.path.exists("data.db"):
os.remove("data.db")
os.system("touch data.db")
os.system("chmod 664 data.db")
# データベース接続
%sql sqlite:///data.db
'Connected: @data.db'
%%sql
CREATE TABLE ClassA (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE ClassB (
id INTEGER PRIMARY KEY,
name TEXT
);
INSERT INTO ClassA (name) VALUES
('佐藤さん'),
('鈴木さん'),
('高橋さん');
INSERT INTO ClassB (name) VALUES
('佐藤さん'),
('田中さん'),
('伊藤さん');
* sqlite:///data.db
Done.
Done.
3 rows affected.
3 rows affected.
[]
%%sql
SELECT * FROM ClassA;
* sqlite:///data.db
Done.
| id | name |
|---|---|
| 1 | 佐藤さん |
| 2 | 鈴木さん |
| 3 | 高橋さん |
%%sql
SELECT * FROM ClassB;
* sqlite:///data.db
Done.
| id | name |
|---|---|
| 1 | 佐藤さん |
| 2 | 田中さん |
| 3 | 伊藤さん |
UNION: 重複を排除して統合
UNION を使うと、2つの結果セットを統合した後、重複する行を削除 する。
query = """
SELECT name FROM ClassA
UNION
SELECT name FROM ClassB;
"""
with sqlite3.connect("data.db") as conn:
df = pl.read_database(query, connection=conn)
display(df)
shape: (5, 1)
| name |
|---|
| “伊藤さん” |
| “佐藤さん” |
| “田中さん” |
| “鈴木さん” |
| “高橋さん” |
両方のクラスにいる「佐藤さん」は1行だけ表示されている。 内部的にソートやハッシュ処理が行われ、重複が削除されているためである。
UNION ALL: 重複をそのまま表示
UNION ALL を使うと、重複削除を行わず、単純に結果を縦に結合する。
query = """
SELECT name FROM ClassA
UNION ALL
SELECT name FROM ClassB;
"""
with sqlite3.connect("data.db") as conn:
df = pl.read_database(query, connection=conn)
display(df)
shape: (6, 1)
| name |
|---|
| “佐藤さん” |
| “鈴木さん” |
| “高橋さん” |
| “佐藤さん” |
| “田中さん” |
| “伊藤さん” |
「佐藤さん」が2回表示されている。
重複削除の処理が走らないため、UNION よりも 高速 に動作する。
まとめ
- UNION: 重複を削除する(遅い)
- UNION ALL: 重複を削除しない(速い)
重複があっても問題ない場合や、そもそも重複しないことがわかっている場合は、パフォーマンスのために必ず UNION ALL を使うようにしよう。