こんにちは~。たにすぎです。
入社してそろそろ3か月経ちますが、入ったときには既にみんなマスク着用だったので、何かの拍子に外した姿を見ると「誰だ……?」と2秒くらい固まります。
いやあ、早く素顔で笑える日が来てほしいですね。
さて、タイトルで既に原因お分かりの方もいるかと思いますが、
NULLな文字列をCONCATでつなげたら悲しい思いをしたのでその話をします。
今回の状況
「苗字(半角スペース)名前」の形で氏名を表示する時に何も考えずにCONCATでつなげた結果を表示しようとしたら痛い目にあいました。
こういうデータがあって、
以下のようなクエリを書きました。
SELECT CONCAT(name_last, ' ', name_first) AS name FROM scores s
結果
あれ……? 1番下が何も表示されないな。
なんで消えちゃうの
思ってたのと違う結果になったのでドキュメント読みます。
https://dev.mysql.com/doc/refman/5.6/ja/string-functions.html#function_concat
引数のいずれかかが NULL である場合、CONCAT() は NULL を返します。
はい。
つなげる文字列の中で1つでもNULLがあると、結果がNULLになるんですね。知らなかった……
書き換え案
氏名で片方がない場合はあまりなさそうですが、住所で建物名がないとかは割とありそうなのでなんとかしたいです。
IFNULL
IFNULLをつかってNULLの場合は空に置き換えてから繋ぐように書き換えてみます。
SELECT
CONCAT(name_last, ' ', name_first) AS 'IFNULL使ってないname',
CONCAT( IFNULL(name_last,''), ' ', IFNULL(name_first, '') ) AS 'IFNULL使ったname'
FROM users u
できたできた。
COALESCE
COALESCEでも結果は同じだけど、なんだかもったいないような……
SELECT
CONCAT(name_last, ' ', name_first) AS 'そのままCONCAT',
CONCAT( COALESCE(name_last,''), ' ', COALESCE(name_first, '') ) AS 'COALESCE使ったname'
FROM users u
GROUP_CONCAT
GROUP_CONCATは複数行の結果をカンマ区切りで返してくれる関数です。
こちらはどうなるんでしょう?
SELECT GROUP_CONCAT(name_last), GROUP_CONCAT(name_first)
FROM users
あ、GROUP_CONCATの方はNULLは気にしないでくれるみたいですね。
https://dev.mysql.com/doc/refman/5.6/ja/group-by-functions.html#function_group-concat
おわりに
めんどくさがるのよくないですね!
何らかの理由でIF_NULLが使えない場合はCASEとIS_NULLで対応したらいいのかな……
おまけ: PostgreSQLの場合は?
これは完全に言い訳なんですが、ここ数年はPostgreSQLをメインに使っていて、そっちはNULL含む項目をCONCATで繋げても無視した結果を返してくれていたんです……
でもそういえばCONCAT使わずに「||」(パイプ)で繋げた場合はNULLになってましたね……
SELECT CONCAT(name_last, ' ', name_first) AS "CONCATの結果", name_last || ' ' || name_first AS "パイプの結果" FROM users