はじめに
日頃から Amazon Redshift を使っていて、複数行の値を1行にまとめたいときに LISTAGG を使っていました。
ただ、他のデータベース(MySQLやPostgreSQLなど)で同じことをしようとすると、書き方が微妙に違うことに気付きました。
そこで今回は、主要な3つのデータベース(Oracle/PostgreSQL/MySQL)で「複数行の値を1行にまとめる方法」を整理します。
DBごとの関数対応表
| データベース | 関数名 | 例 |
|---|---|---|
| Oracle / Redshift | LISTAGG | LISTAGG(name, '区切り文字') |
| PostgreSQL | string_agg | string_agg(name, '区切り文字') |
| MySQL | GROUP_CONCAT | GROUP_CONCAT(name SEPARATOR '区切り文字') |
テーブルの例
itemsテーブル
| id | name |
|---|---|
| 1 | りんご |
| 2 | みかん |
| 3 | バナナ |
| 4 | ぶどう |
| 5 | もも |
各DBでの書き方例
Oracle / Redshiftの場合
SELECT
LISTAGG(name, ', ') AS names
FROM
items;
→ 出力例
| names |
|---|
| りんご, みかん, バナナ, ぶどう, もも |
LISTAGG(列名, ', ') で複数行の値をカンマ区切りにまとめられます。
※RedshiftはPostgreSQLをベースにしていますが、string_aggは使えず、LISTAGGが利用できるようです。
PostgreSQLの場合
SELECT
string_agg(name, ', ') AS names
FROM
items;
string_agg(列名, ', ') で複数行の値をカンマ区切りにまとめられます。
MySQLの場合
SELECT
GROUP_CONCAT(name SEPARATOR ', ') AS names
FROM
items;
GROUP_CONCAT はSEPARATOR に区切り文字を指定します(デフォルトはカンマ,)。
補足:DISTINCTで重複を除外する
どのDBでも、DISTINCTを使うと重複を除外して連結できます。
-- PostgreSQLの例
SELECT
string_agg(DISTINCT name, ', ') AS names
FROM
items;
まとめ
-
LISTAGGはOracle / Redshiftで利用可能 -
PostgreSQLではstring_agg -
MySQLではGROUP_CONCAT -
DISTINCTで重複を除外できる
さいごに
SQL Fiddleというサイト(以下リンク先)を使うと気軽にブラウザで各DBを試すことができて便利でした。
https://sqlfiddle.com/