複数レコードのデータを連結して取得したい
MySQL(MariaDB)で、GROUP_CONCAT
を使って、縦に並んだ複数レコードのデータを1列(カンマ区切り)で取得するSQLを書く方法をまとめます。
SQL Serverでは、FOR XML PATH('')
を使用して取得できます。
[SQL Server] 縦に並んだデータを横にカンマ区切りの列データで取得する方法
上記記事では SQL Server の例をまとめていますが今回は MySQL で似たようなことをやってみます。
GROUP_CONCAT
MySQL(MariaDB)では GROUP BY でグループ化(Group By)した上で、GROUP_CONCAT
を使用することで実現します。
GROUP_CONCAT
は集約関数の一つで、SUM()
や MAX()
と同じく、値のセットに対して処理を行います。Group By
によって集約されたグループから、文字列として連結した値を取得します。
サンプル
CREATE TABLE sales
(`id` int, `item` varchar(30), `date` datetime)
;
INSERT INTO sales
(`id`, `item`, `date`)
VALUES
(1, '商品C', '2017-04-01 00:00:00'),
(2, '商品B', '2017-04-01 00:00:00'),
(3, '商品A', '2017-04-01 00:00:00'),
(4, '商品A', '2017-04-02 00:00:00'),
(5, '商品B', '2017-04-02 00:00:00'),
(6, '商品C', '2017-04-03 00:00:00'),
(7, '商品A', '2017-04-03 00:00:00'),
(8, '商品D', '2017-04-04 00:00:00'),
(9, '商品C', '2017-04-05 00:00:00'),
(10, '商品C', '2017-04-05 00:00:00')
;
例えば上記のようなデータで考えます。商品の売り上げデータを保持しているテーブルです。フィールドは以下の3つです。
- id: 主キー
- item: 商品名
- date: 売上日
ここで売上日ごとにデータを集約し、商品名を連結したデータを取得したいという時に、GROUP_CONCAT
が使えます。例えばそれぞれの商品の直近の売上日を知りたければ Group By + Max()
で取得できるように、集約したデータをに対して連結した文字列を GROUP_CONCAT
で取得できるということです。
SELECT
GROUP_CONCAT(item) AS 売れた商品,
date AS 売上日
FROM sales
GROUP BY date
売れた商品 | 売上日 |
---|---|
商品C,商品B,商品A | 2017-04-01T00:00:00Z |
商品A,商品B | 2017-04-02T00:00:00Z |
商品C,商品A | 2017-04-03T00:00:00Z |
商品D | 2017-04-04T00:00:00Z |
商品C,商品C | 2017-04-05T00:00:00Z |
GROUP_CONCATの構文
GROUP_CONCAT([DISTINCT] expr [,expr …]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name …]]
[SEPARATOR str_val])
GROUP_CONCAT
の基本は「連結する列を指定してカンマ区切りで取得」ですが、それ以外にもパラメータで細かく指定することが可能です。
例えば、デフォルトの連結用の文字列(SEPARATOR
)はカンマ(,)ですが、これを変更することが可能です。連結する順番も ORDER BY
で指定できます。DISTINCT
で重複を省くこともできます。
構文は上述の通りです。。ここでは、連結文字と並び順と重複の除去を設定する例を以下に示します。
SELECT
GROUP_CONCAT(DISTINCT item ORDER BY item ASC SEPARATOR '/') AS 売れた商品,
date AS 売上日
FROM sales
GROUP BY date
売れた商品 | 売上日 |
---|---|
商品A/商品B/商品C | 2017-04-01T00:00:00Z |
商品A/商品B | 2017-04-02T00:00:00Z |
商品A/商品C | 2017-04-03T00:00:00Z |
商品D | 2017-04-04T00:00:00Z |
商品C | 2017-04-05T00:00:0 |
- 最終行のデータから「商品C」の重複が除去されている。
- 区切り文字が指定したスラッシュ(/)になっている。
- 列挙された商品名の並び順が商品名昇順になっている。
3つのパラメータを設定したため、以上3点に違いがあります。
以上、使いこなせると便利な GROUP_CONCAT
のまとめでした。
コメントを書く