[SQL] UNIONとUNION ALLの違い

今回はSQLの UNIONUNION 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つのクラス ClassAClassB の生徒名簿を作成する。 「佐藤さん」は両方のクラスに存在するものとする。

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.
idname
1佐藤さん
2鈴木さん
3高橋さん
%%sql
SELECT * FROM ClassB;
 * sqlite:///data.db
Done.
idname
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 を使うようにしよう。