読者です 読者をやめる 読者になる 読者になる

文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

MySQLで複数レコードからカンマ区切りの結合文字列を生成する

mysql

複数のカラムをカンマ区切りで結合するケース、よくありますよね。
今回はmysqlで実装してみます。

非常に簡単です。concat_wsを使うだけです。

mysql> select concat_ws (',', 'aaa', '', 'bbb', null, 'ccc');
+------------------------------------------------+
| concat_ws (',', 'aaa', '', 'bbb', null, 'ccc') |
+------------------------------------------------+
| aaa,,bbb,ccc                                   |
+------------------------------------------------+

第一引数がデリミタです。
concat_wsはconcatと違い、nullが混入してもnullは返りません。
↑のようにnullをバッチリ無視してくれます!しかし、空文字は突破されますね。では、

mysql> select concat_ws (',', nullif('aaa', ''), nullif('', ''), nullif('bbb', ''), nullif(null, ''), nullif('ccc', ''));
+------------------------------------------------------------------------------------------------------------+
| concat_ws (',', nullif('aaa', ''), nullif('', ''), nullif('bbb', ''), nullif(null, ''), nullif('ccc', '')) |
+------------------------------------------------------------------------------------------------------------+
| aaa,bbb,ccc                                                                                                |
+------------------------------------------------------------------------------------------------------------+

ちょっと冗長ですが、nullifすれば空文字も対処できます。
よくある利用ケースは、複数のカラムをconcat_wsで1カラムにまとめ、アプリ側でsplitするような場合ですね。
1カラムにまとめてしまうことで、
例えば名称等、同系統のカラムが100個有った場合、concat_wsで1カラムにまとめてしまえば、
アプリ側(例えばjspで)splitして<c:forEach>させればnullチェックは不要だし、
要素の中身を気にしなくてもよくなります。

他の利用ケースとして、ストアドプロシージャでも使えます。
例えば、チェックボックスでチェックされた場合のみ、WHERE句にAND条件追加、とか。
文字列でWHERE句の条件を作っておき、
concat_ws ('and ', nullif(condition1, ''), nullif(condition2, ''), nullif(condition3, ''))
とかやれば、動的な条件も最小限のコードで書くことができちゃいます。これは便利。