PostgreSQLで1行を複数行に分けるには?UNIONで実現するシンプルなSQL構文を解説

※ この記事にはアフィリエイトリンクが含まれます

SQLを扱っていると、1行に複数の値が詰め込まれたデータを「縦方向」に展開したくなる場面があったりすると思います。
たとえば、次のようなテーブルを想像してみてください。

id | name | score1 | score2 | score3
----+------+--------+--------+--------
 1  | 山田 |   80   |   90   |   70

このような“横持ち”のデータを、そのまま集計や可視化に使うのは意外と不便です。
多くのBIツールや分析SQLは、「縦持ち(項目名と値が行ごとに分かれている形)」の方が扱いやすいからです。

理想は次のような形です。

id | name | subject | score
----+------+----------+-------
 1  | 山田 | score1   | 80
 1  | 山田 | score2   | 90
 1  | 山田 | score3   | 70

このように「1行に横並びのデータを、複数行に分割して見せる」処理は、PostgreSQLではいくつかの方法で実現できます。
代表的なのは UNNESTregexp_split_to_table() などの関数を使う方法ですが、
実は UNION を使えば、シンプルなSQL構文だけで同じことが可能です。

この記事では、
「PostgreSQLでUNIONを使って1行のデータを複数行で表示する方法」
について、実務で使えるサンプルを交えながら、わかりやすく解説していきます。

目次

UNIONでカラムを縦に連結する

UNION は、複数のSELECT文の結果を1つにまとめるためのSQL構文です。

PostgreSQLに限らず、SQL標準として多くのDBで利用できます。

例えば、次のような2つのSELECT文があるとします。

SELECT 'A' AS label
UNION ALL
SELECT 'B' AS label;

結果は次のように、2つのSELECTが縦方向に結合された形になります。

label
------
A
B

つまり、UNION は「行を縦に並べる」ための構文です。

これを応用すれば、「1行の中にある複数のカラム」を複数行として表示することができます。

例:1行データを3行に分割する

それでは、実際にサンプルテーブルを用いて試してみましょう。

▼サンプルテーブルのCREATE文

CREATE TABLE test_scores (
  id SERIAL PRIMARY KEY,
  name TEXT,
  score1 INTEGER,
  score2 INTEGER,
  score3 INTEGER
);

INSERT INTO test_scores (name, score1, score2, score3)
VALUES ('山田', 80, 90, 70);

この状態では、1行の中に score1score3 の値が並んでいます。
これを次のように UNION ALL を使って縦持ちに展開します。

▼UNIONを使った変換SQL

SELECT id, name, 'score1' AS subject, score1 AS score FROM test_scores
UNION ALL
SELECT id, name, 'score2' AS subject, score2 AS score FROM test_scores
UNION ALL
SELECT id, name, 'score3' AS subject, score3 AS score FROM test_scores;

▼実行結果

idnamesubjectscore
1山田score180
1山田score290
1山田score370

これで、横方向に並んでいたデータを縦方向に展開できました。

注意点

この方法の唯一の弱点は、「列数が増えるほどSQLが長くなる」点です。

例えば、10個のスコアを持つテーブルを縦にしたい場合は、10回分のUNION ALL を書かなければなりません。

SELECT id, 'score1' AS item, score1 AS value FROM test_scores
UNION ALL
SELECT id, 'score2' AS item, score2 AS value FROM test_scores
-- (中略)
UNION ALL
SELECT id, 'score10' AS item, score10 AS value FROM test_scores;

対処法:ビュー化する

よく使う変換であれば、SQLをビュー化してしまうのがおすすめです。

CREATE VIEW v_sales_vertical AS
SELECT staff_name, 'Q1' AS quarter, q1_sales AS sales FROM sales_summary
UNION ALL
SELECT staff_name, 'Q2' AS quarter, q2_sales AS sales FROM sales_summary
UNION ALL
SELECT staff_name, 'Q3' AS quarter, q3_sales AS sales FROM sales_summary
UNION ALL
SELECT staff_name, 'Q4' AS quarter, q4_sales AS sales FROM sales_summary;

こうすることで、次回からは以下のように簡単に呼び出せます。

SELECT * FROM v_sales_vertical;

まとめ

PostgreSQLで「1行に収まったデータを複数行で表示したい」場合、
UNIONUNION ALL を使うだけで、驚くほどシンプルに実現できます。

特別な関数を覚えなくても、SQLの基礎構文だけで“横持ち → 縦持ち”変換が可能です。
特に、レポート生成や一時的なデータ分析、他システム連携の前処理などではこの方法が非常に実用的です。

実際の現場では、アプリケーションの設計や集計要件によって「横持ち」データが生まれることは少なくありません。
そんなときでも、UNION ALL さえ理解していれば、すぐに“見やすい形”に整形できるのが強みです。

PostgreSQLは、現場でも広く使われている信頼性の高いデータベースです。
もしこれから本格的に学び、実務で通用する力をつけたい方には、RareTECHをチェックしてみてください。
実案件ベースのカリキュラムで、あなたのスキルを次のステージへ引き上げてくれるはずです。


なんくる

「本当にエンジニアとしてやっていけるか不安…」という方も、実践的な開発に関わることで、転職後の働き方を事前に体感できますよ。

実務で使えるDBスキルとともに、プログラミングスキルをちゃんと身につけたいなら、
RareTECH無料カウンセリングで、学ぶ目的やゴールをプロと一緒に明確にしてみましょう。独学では得られない「実践的な成長の道筋」が見えてきます。


もしこの内容を通して、PostgreSQLについてさらに理解を深めたいと感じられたなら、信頼できる講座や書籍を紹介した別記事をご覧いただくのも良いかと思います。ご自身の学びに、きっとお役立ていただけるはずです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

沖縄出身のエンジニアです。IT業界で5年以上の経験があり、主にC#やPHPを使って開発を行ってきました。新しい技術にも興味があり、日々学びながらスキルアップを目指しています。

コメント

コメントする

CAPTCHA


目次