Webサイト制作コースのお申し込みはこちら Webサイト制作コースのお申し込みはこちら

MySQLの文字列結合の使い方について、サンプルSQLを紹介しながらまとめています。

以下、データベースとして、MySQLのサンプルデータベースEmployeesを使っています。

サンプルデータベースのインストール方法は、下記を参考にしてください。

【関連記事】
MySQLの入門には、GUIツールで慣れ、サンプルDBを使った学習が効果的

MySQLで文字列を連結するには、CONCATを使う

文字列を連結するには、次のようにします。

mysql> select CONCAT("By", "The", "Way");
+----------------------------+
| CONCAT("By", "The", "Way") |
+----------------------------+
| ByTheWay                   |
+----------------------------+

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.5 文字列関数 CONCAT

テーブルのカラムを結合するには、CONCATにカラム名を指定

CONCATの引数にカラム名を指定することで、テーブルのカラムを結合できます。

mysql> select CONCAT( dept_no, ":", dept_name) from departments;
+----------------------------------+
| CONCAT( dept_no, ":", dept_name) |
+----------------------------------+
| d009:Customer Service            |
| d005:Development                 |
| d002:Finance                     |
| d003:Human Resources             |
| d001:Marketing                   |
| d004:Production                  |
| d006:Quality Management          |
| d008:Research                    |
| d007:Sales                       |
+----------------------------------+

上記SQLは、departments(部署)テーブルのdept_no(部署番号)と”:”(コロン)とdept_name(部署名)を結合します。

複数の文字列を入れ子で連結可能

CONCATの引数に、CONCATを指定する入れ子構造も可能です。

mysql> select CONCAT("This MySQL version is ",CONCAT("5.","7.","28"));
+---------------------------------------------------------+
| CONCAT("This MySQL version is ",CONCAT("5.","7.","28")) |
+---------------------------------------------------------+
| This MySQL version is 5.7.28                            |
+---------------------------------------------------------+

その他、CONCATの基本的な使い方は以下の記事を参考になさってください。

【関連記事】
MySQLのCONCATとは?概要と基礎〜応用の使い方を解説!

CONCATの使い方応用編

結合文字列にNULLが含まれると、結果がNULLになるのを回避するにはIFNULL

CONCATの引数のどこかに一つでもNULLが入っていると、結合結果がNULLになります。

select CONCAT("This","Is",NULL);
+--------------------------+
| CONCAT("This","Is",NULL) |
+--------------------------+
| NULL                     |
+--------------------------+

IFNULLを組み合わせて、NULLの箇所を別の文字列や空文字に変換可能です。IFNULL()は、第一引数がNULLだった場合に第二引数を返す関数です。

mysql> select CONCAT("This","Is",IFNULL(NULL,""));
+-------------------------------------+
| CONCAT("This","Is",IFNULL(NULL,"")) |
+-------------------------------------+
| ThisIs                              |
+-------------------------------------+

結合文字列に改行を入れるには、改行コードをCONCATする

CONCATには、制御コード(改行コード)を指定することも可能です。

mysql> select CONCAT("MySQL","\n", "5.7.28");
+--------------------------------+
| CONCAT("MySQL","\n", "5.7.28") |
+--------------------------------+
| MySQL
5.7.28                   |
+--------------------------------+

上記SQLでは、”\n”(Linuxの改行コード)を結合して、「MySQL」+改行+「5.7.28」にしています。

GROUP_CONCATでGROUP BY集計を各1行に集約

GROUP_CONCATで、複数レコードを1つの文字列に結合できます。

mysql> select GROUP_CONCAT(dept_name SEPARATOR ",") from departments;
+-------------------------------------------------------------------------------------------------------------+
| GROUP_CONCAT(dept_name SEPARATOR ",")                                                                       |
+-------------------------------------------------------------------------------------------------------------+
| Customer Service,Development,Finance,Human Resources,Marketing,Production,Quality Management,Research,Sales |
+-------------------------------------------------------------------------------------------------------------+

上記のSQLは、departmens(部署)テーブルのdept_name(部署名)を”,”(カンマ)で連結して一つの文字列にします。

参考)MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.19.1 GROUP CONCAT関数

GROUP BYと組み合わせて、複数行のデータを1行にまとめて簡潔に表示することが可能です。

SELECT departments.dept_name, 
       GROUP_CONCAT(DISTINCT titles.title SEPARATOR ',') 
FROM   employees 
       LEFT JOIN dept_emp ON employees.emp_no = dept_emp.emp_no 
       LEFT JOIN departments ON dept_emp.dept_no = departments.dept_no 
       LEFT JOIN titles ON employees.emp_no = titles.emp_no 
GROUP  BY departments.dept_name;

上記のSQLは、部署名(departments.dept_name)ごとに所属する職種(titles.title)をカンマで連結して部署ごとに1行づつ表示します。実行するとこうなります。

+--------------------+-----------------------------------------------------------------------------------------+
| dept_name          | GROUP_CONCAT(distinct titles.title SEPARATOR ',')                                       |
+--------------------+-----------------------------------------------------------------------------------------+
| Customer Service   | Assistant Engineer,Engineer,Manager,Senior Engineer,Senior Staff,Staff,Technique Leader |
| Development        | Assistant Engineer,Engineer,Manager,Senior Engineer,Senior Staff,Staff,Technique Leader |
| Finance            | Manager,Senior Staff,Staff                                                              |
| Human Resources    | Manager,Senior Staff,Staff                                                              |
| Marketing          | Manager,Senior Staff,Staff                                                              |
| Production         | Assistant Engineer,Engineer,Manager,Senior Engineer,Senior Staff,Staff,Technique Leader |
| Quality Management | Assistant Engineer,Engineer,Manager,Senior Engineer,Technique Leader                    |
| Research           | Assistant Engineer,Engineer,Manager,Senior Engineer,Senior Staff,Staff,Technique Leader |
| Sales              | Manager,Senior Staff,Staff                                                              |
+--------------------+-----------------------------------------------------------------------------------------+

where条件にCONCATを使うと遅い

SQLのwhere節にCONCATを指定することも可能です。

mysql> select * from employees where concat(first_name," ",last_name) = "Jayson Mandell";
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date  |
+--------+------------+------------+-----------+--------+------------+
|  10096 | 1954-09-16 | Jayson     | Mandell   | M      | 1990-01-14 |
+--------+------------+------------+-----------+--------+------------+

ただし、concatで条件指定した場合、インデックスが使用できないため、対象データが多くなるほどレスポンスが悪くなります。

【関連記事】
MySQLのインデックス作成方法 効いてないと思ったらexplainで確認する

employeesテーブルのfist_nameとlast_nameにインデックスを設定して、試してみます。

mysql> alter table employees add index index3(first_name,last_name);

上記SQLは、employeesのfirst_nameとlast_nameの組み合わせにindex3という名前でインデックスを設定します。

mysql> explain select * from employees where concat(first_name," ",last_name) = "Jayson Mandell";
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299025 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+

concatをwhereに使ったSQLをexplainして、実行計画をチェックしてみると「type=ALL」のテーブルフルスキャンが実行されています。

concatを使わないwhere条件に書き換えると、以下のようになりました。

mysql> explain select * from employees where first_name = "Jayson" and last_name="Mandell";
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------+------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref         | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------+------+----------+-------+
|  1 | SIMPLE      | employees | NULL       | ref  | index3        | index3 | 34      | const,const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------+------+----------+-------+

設定したインデックスindex3が利用されていることが確認できます。

データの多いテーブルに対しては、where条件にconcatを使うのを避けるのが良いでしょう。

まとめ

ポテパンダの一言メモ
  • MySQLで文字列を連結するには、CONCATを使う
  • 複数レコードを連結するには、GROUP_CONCATを使う。GROUP BYと組み合わせて、1行に複数データを集約可能。
  • NULLを含む文字列を連結するには、IFNULLを組み合わせてNULLを別の文字列に変換する
  • WHERE節で、件数の多いテーブルにCONCATを使うと、インデックスが利用できないためパフォーマンスが低下する

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。