お知らせ
2023.12.5(Tue)
目次
こんにちは。最近SQLを使う機会が多い関口です。
突然ですが、そこのアナタ! 同じような取得結果のSQLを、取得条件が違うからと言って複数作成していませんか? ……それ、1つのSQLで取得できますよ!
テンション高めで始まりました。今回は、検索結果を結合して取得できる、UNIONとUNION ALLの使い方を紹介していきます!
検証で使用した環境は以下の通りです。
UNIONは、複数の検索結果(SELECT)を結合して取得できる構文です。検索結果同士の項目数およびデータ型が一致している必要があります。また、UNIONでは、DISTINCTと同様に、結果から重複している行を削除して取得します。
今回使用するテーブルは下記の通り作成しました。
// テーブル作成SQL
CREATE TABLE public.table_a (
user_id integer not null
, target_date date not null
, status integer not null
, calc_value integer
, primary key (user_id, target_date)
);
CREATE TABLE public.table_b (
user_id integer not null
, target_date date not null
, status integer not null
, calc_value integer
, primary key (user_id, target_date)
);
// テーブル内データ
SELECT * FROM table_a;
user_id | target_date | status | calc_value
---------+-------------+--------+------------
1 | 2022-04-30 | 1 | 132
1 | 2022-05-01 | 2 | 31
1 | 2022-05-02 | 1 | 10
2 | 2022-04-30 | 2 | 65
2 | 2022-05-01 | 2 | 101
2 | 2022-05-02 | 1 | 22
3 | 2022-05-01 | 1 | 52
3 | 2022-05-02 | 1 | 15
4 | 2022-04-30 | 2 | 100
(9 行)
SELECT * FROM table_b;
user_id | target_date | status | calc_value
---------+-------------+--------+------------
1 | 2022-04-30 | 2 | 32
1 | 2022-05-01 | 2 | 55
1 | 2022-05-02 | 1 | 10
2 | 2022-05-01 | 1 | 101
2 | 2022-05-02 | 1 | 22
3 | 2022-05-01 | 1 | 15
3 | 2022-05-02 | 2 | 88
4 | 2022-04-30 | 1 | 42
(8 行)
// 実行SQL
SELECT
user_id
, target_date
, calc_value
FROM
table_a
WHERE
target_date = '2022/05/02'
UNION
SELECT
user_id
, target_date
, calc_value
FROM
table_b
WHERE
status = '1';
// 実行結果
user_id | target_date | calc_value
---------+-------------+------------
1 | 2022-05-02 | 10
2 | 2022-05-01 | 101
2 | 2022-05-02 | 22
3 | 2022-05-01 | 15
3 | 2022-05-02 | 15
4 | 2022-04-30 | 42
(6 行)
UNION ALLは、UNIONと同様に、複数の検索結果(SELECT)を結合して取得できる構文です。UNION ALLでは、結果から重複している行もそのまま取得されます。重複チェックを行わない分、UNIONよりも処理速度が速くなります。
先ほど使用したSQLを、UNION ALLに変えて実行してみます!
// 実行SQL
SELECT
user_id
, target_date
, calc_value
FROM
table_a
WHERE
target_date = '2022/05/02'
UNION ALL
SELECT
user_id
, target_date
, calc_value
FROM
table_b
WHERE
status = '1';
// 実行結果
user_id | target_date | calc_value
---------+-------------+------------
1 | 2022-05-02 | 10
1 | 2022-05-02 | 10
2 | 2022-05-01 | 101
2 | 2022-05-02 | 22
2 | 2022-05-02 | 22
3 | 2022-05-01 | 15
3 | 2022-05-02 | 15
4 | 2022-04-30 | 42
(8 行)
では試しに、項目数の違う検索結果をUNIONで結合してみましょう。
// 実行SQL SELECT user_id , target_date , calc_value FROM table_a UNION ALL SELECT user_id , target_date FROM table_b; // 実行結果 ERROR: すべてのUNION問い合わせは同じ列数を返す必要があります 行 9: user_id
こちらは私が実際にハマったエラーになります。先ほど使用したSQLに、並び替え(ORDER BY)を追加します。
// 実行SQL SELECT user_id , target_date , calc_value FROM table_a WHERE target_date = '2022/05/02' ORDER BY target_date UNION ALL SELECT user_id , target_date , calc_value FROM table_b WHERE status = '1' ORDER BY target_date; // 実行結果 ERROR: "UNION"またはその近辺で構文エラー 行 11: UNION ALL
// 実行SQL
SELECT
user_id
, target_date
, calc_value
FROM
table_a
WHERE
target_date = '2022/05/02'
UNION ALL
SELECT
user_id
, target_date
, calc_value
FROM
table_b
WHERE
status = '1'
ORDER BY
target_date
, user_id;
// 実行結果
user_id | target_date | calc_value
---------+-------------+------------
4 | 2022-04-30 | 42
2 | 2022-05-01 | 101
3 | 2022-05-01 | 15
1 | 2022-05-02 | 10
1 | 2022-05-02 | 10
2 | 2022-05-02 | 22
2 | 2022-05-02 | 22
3 | 2022-05-02 | 15
(8 行)
いかがでしたでしょうか。
UNIONを知らなかった方も、そうでない方にも、お役に立てれば幸いです。UNIONの他にも、検索結果を結合できる構文がありますので、またの機会に紹介したいと思います!SQLは奥が深いですね~!
《関連記事》