MySQL

MySQL

【MySQL】CONCATとGROUP_CONCATを駆使して、複数レコードの文字列を結合してみる。

2019/03/06

MySQLで複数行の文字列レコードをひと纏めにして、1レコードとして出力する方法を備忘録としてポストします。

以下の旅行テーブルのレコードを利用します。

travel_table_01

CONCAT()

MysqlのCONCAT()関数は文字列の結合を行う関数。
使い方は以下のように。

CONCAT() 書式

[sql]
CONCAT(文字列1, 文字列2, ・・・文字列N)
[/sql]

CONCAT() 実例

全レコードを半角カンマ区切りで取得

[sql]
SELECT
CONCAT(id, ',', CONVERT(name_first USING cp932), ',', hotel_id, ',', room_number) AS Record
FROM
travels
[/sql]

結果

travel_table_02

↑ CSV出力などで扱い易い、半角カンマ区切りでレコードを作ってみました。

CONCAT() 実例2

CONCAT()の引数に NULL が含まれる場合、結果がNULLとなってしまいます。
以下のレコードで試します。

travel_table_04

CONCAT() NULLを含む場合の実例

全レコードを半角カンマ区切りで取得

[sql]
SELECT
CONCAT(id, ',', CONVERT(name_family USING cp932), ',', CONVERT(name_first USING cp932), ',', hotel_id, ',', room_number) AS Record
FROM
travels
[/sql]

結果

travel_table_05

↑ 4,7の結果がNULLで返るために、空白となっています。

GROUP_CONCAT()

GROUP_CONCAT()関数は複数レコードを1行に纏めることが出来ます。
セパレータを指定することも可能です。

GROUP_CONCAT() 書式

[sql]
GROUP_CONCAT(カラム名 SEPARATOR ',' )
[/sql]

GROUP_CONCAT() 実例

ホテル別に「姓名」を1カラムに結合して出力する実例

[sql]
SELECT
hotel_id,
GROUP_CONCAT(name_family, name_first SEPARATOR ', ') AS name
FROM
travels
GROUP BY
hotel_id
[/sql]

↑ hotel_id へ GROUP BY を効かせ、データを hotel_id ごとにするのも忘れずに。

結果

travel_table_03

GROUP_CONCAT() NULLを含む場合の実例

NULLを含む場合の実例。
以下レコードを使用します。

travel_table_04

ホテル別に「姓名」を1カラムに結合して出力する実例

[sql]
SELECT
hotel_id,
GROUP_CONCAT(name_family, name_first SEPARATOR ',') AS name
FROM
travels
GROUP BY hotel_id
[/sql]

結果

travel_table_06

↑ 4,7のレコードが抜けています。

本題

CONCAT()とGROUP_CONCAT()を駆使してみる

本題 実例1

ホテル別に「名」を出力、名がNULLの場合は「名無し」を代替出力

[sql]
SELECT
hotel_id,
CONCAT(
IFNULL(GROUP_CONCAT(name_family SEPARATOR ', '), '名無し'), ' '
) AS name
FROM
travels
GROUP BY
hotel_id
[/sql]

本題 実例2 実例1の書き方を変えてみる

結果は同じですが、CONCATとGROUP_CONCATの順番を入れ替えても書けます。

[sql]
SELECT
hotel_id,
GROUP_CONCAT(
CONCAT(IFNULL(name_family, '名無し')) SEPARATOR ', '
) AS name
FROM
travels
GROUP BY
hotel_id
[/sql]

travel_table_08

本題 実例3

結果が NULL のままでは分かりにくいので、姓が抜けている場合は「姓」、名が抜けている場合は「名」と代替表示させてみます。

「姓」がNULLの場合は「姓」、「名」がNULLの場合は「名」を代替出力

[sql]
SELECT
hotel_id,
GROUP_CONCAT(
CONCAT(IFNULL(name_family, '姓')),CONCAT(IFNULL(name_first, '名')) SEPARATOR ', '
) AS name
FROM
travels
GROUP BY
hotel_id
[/sql]

結果

travel_table_07

NULLのレコードも代替テキストで表示される、欲しい形となりました。
SQL、やはり奥深いけど便利ですね。

やっぱりCakePHPなどフレームワークを使っていても、SQLは書くべきかも知れませんね。

-MySQL
-, , , , ,