【Oracle】UNION・UNION ALLを使ってみよう!

Oracle

前回は、行数を限定しデータを取得できる OFFSET ~ FETCH とROWNUMについて説明しました。今回は、2つのSELECT文からそれぞれの検索結果を足し合わせた結果(和集合)を返してくれる、UNION と UNION ALL について説明します。

和集合

UNION
和集合
2つの検索結果を
足し合わせたもの
和集合のイメージ

データ準備

UNION、UNION ALL を試すためにテーブルを作成し、データを追加します。

-- テーブルの作成
-- 家計簿テーブル1
CREATE TABLE household_account1 (
    id INT PRIMARY KEY,
    transaction_date DATE,
    expense VARCHAR2(20),
    memo VARCHAR2(80),
    deposit INT,
    withdrawal INT
);

-- 家計簿テーブル2
CREATE TABLE household_account2 (
    id INT PRIMARY KEY,
    transaction_date DATE,
    expense VARCHAR2(20),
    memo VARCHAR2(80),
    deposit INT,
    withdrawal INT
);

-- データの登録
-- 家計簿テーブル1
INSERT
  ALL INTO household_account1
VALUES
  (1, TO_DATE('2024-02-10', 'YYYY-MM-DD'), '給料', '2月分', 150000, 0)
INTO
  household_account1
VALUES
  (2, TO_DATE('2024-02-13', 'YYYY-MM-DD'), '食費', '昼食(くら寿司)', 0, 1880) 
INTO
  household_account1
VALUES
  (3, TO_DATE('2024-02-25', 'YYYY-MM-DD'), '交際費', '飲み会', 0, 4000)
SELECT
  *
FROM
  DUAL;

-- 家計簿テーブル2
INSERT
  ALL INTO household_account2
VALUES
  (1, TO_DATE('2024-03-10', 'YYYY-MM-DD'), '給料', '3月分', 150000, 0)
INTO
  household_account2
VALUES
  (2, TO_DATE('2024-03-05', 'YYYY-MM-DD'), '交通費', 'バス代', 0, 240) 
INTO
  household_account2
VALUES
  (3, TO_DATE('2024-03-18', 'YYYY-MM-DD'), '交際費', '飲み会', 0, 8000)
SELECT
  *
FROM
  DUAL;
日付費目メモ入金額出金額
2024/02/10給料2月分1500000
2024/02/13食費昼食(くら寿司)01880
2024/02/25交際費飲み会04000
家計簿テーブル1
日付費目メモ入金額出金額
2024/03/10給料3月分1500000
2024/03/05交通費バス代0240
2024/03/18交際費飲み会08000
家計簿テーブル2

UNION・UNION ALL の使い方

UNION、UNION ALL は下記のように記述します。

SELECT 文1
UNION (ALL)
SELECT 文2

UNIONとUNION ALL の違いは重複行をまとめるかまとめないかで、UNIONの場合は重複行を1行にまとめてくれてUNION ALLの場合は重複行をまとめずにすべてそのまま返してくれます。

まずは UNION ALL で2テーブルを足し合わせた結果を取得してみます。

SELECT
  TO_CHAR(transaction_date, 'YYYY/MM/DD') AS "日付",
  expense AS "費目",
  memo AS "メモ",
  deposit AS "入金額",
  withdrawal AS "出金額"
FROM
  household_account1
UNION ALL
SELECT
  TO_CHAR(transaction_date, 'YYYY/MM/DD') AS "日付",
  expense AS "費目",
  memo AS "メモ",
  deposit AS "入金額",
  withdrawal AS "出金額"
FROM
  household_account2

しっかりと2テーブル分のデータが取得できました。

日付費目メモ入金額出金額
2024/02/10給料2月分1500000
2024/02/13食費昼食(くら寿司)01880
2024/02/25交際費飲み会04000
2024/03/10給料3月分1500000
2024/03/05交通費バス代0240
2024/03/18交際費飲み会08000
家計簿テーブル1 + 家計簿テーブル2

では、費目がそれぞれかぶっているので UNION を使って重複行をまとめてみたいと思います。

SELECT
  expense AS "費目"
FROM
  household_account1
UNION
SELECT
  expense AS "費目"
FROM
  household_account2

重複行がない費目のデータが取得できました。

費目
交通費
交際費
給料
食費
2テーブルの費目(重複行除外)

処理速度が高いのは UNION ALL

UNIONはデータの重複を除外するために追加の処理が必要なので、UNION ALL よりも処理に時間がかかります。

下記記事はMySQLですが、UNION と UNION ALL の処理速度の違いを実際に測定しグラフにまとめてくれていたのでわかりやすかったです!

【MySQL】UNION と UNION ALL はどっちが処理速度速いの? - Qiita
はじめにこの記事は ミライトデザイン Advent Calendar 2022 の 20 日目の記事となっています。先日はbucchさんの「ReactでGoogleMapの実装をしてみた」でした!…

まとめ

UNIONは重複行を1行にまとめてくれて、UNION ALL は全てのレコードを返してくれるということを覚えておきましょう!

コメント

タイトルとURLをコピーしました