#はじめに
『スッキリわかるSQL入門第二版』5章の練習問題でつまずいたのでまとめます。
p165の問題5-2です。
解答を見ても、SUBSTRINGの文の意味を読み取ることができませんでした。
#問題の解答
あるアンケートの回答者のテーブルがあり、「メールアドレス、国名、性別、年齢」の列がある。それぞれにデータ型が定義されていて、国名は全てNULLとなっている。末尾2文字が国コードとなっているメールアドレスをもとにして、国名列を更新せよ、という問題でした。問題を転記するのが可なのかよくわからないので、問題の詳細はここでは書かないでおきます。
まず、解答はこれでした。
UPDATE 回答者
SET 国名 = CASE SUBSTRING(TRIM(メールアドレス),
LENGTH(TRIM(メールアドレス))-1, 2)
WHEN 'jp' THEN '日本'
WHEN 'uk' THEN 'イギリス'
WHEN 'cn' THEN '中国'
WHEN 'fr' THEN 'フランス'
WHEN 'vn' THEN 'ベトナム' END
わからないのはこの部分。
CASE SUBSTRING(TRIM(メールアドレス),
LENGTH(TRIM(メールアドレス))-1, 2)
ひとつひとつの関数の意味を復習してみます。
#CASE演算子
p144
構文①
CASE 評価する列や式 WHEN 値1 THEN 値1のときに返す値
(WHEN 値2 THEN 値2のときに返す値)...
(ELSE デフォルト値)
END
構文②
CASE WHEN 条件1 THEN 条件1のときに返す値
(WHEN 条件2 THEN 条件2のときに返す値)...
(ELSE デフォルト値)
END
#SUBSTRING関数
p154
「SUBSTRING関数」(読み:サブストリング)or「SUBSTR関数」
どちらを利用できるかは、DBMS製品によって違う。
「何文字目から何文字分」という指定をして文字列の一部分を抽出できる。
#TRIM関数
p152
「TRIM」(読み:トリム)=左右から空白を除去する
(「LTRIM」(エルトリム)=左側から空白を除去する。「RTRIM」(アールトリム)=右側から空白を除去する。)
#LENGTH関数
p152
「LENGTH」(レングス)=文字列の長さを調べる。
(SQL Serverでは「LEN」(レン))p166)
#解答のコードにそれぞれの意味をあてはめてみる
CASE SUBSTRING(TRIM(メールアドレス),
LENGTH(TRIM(メールアドレス))-1, 2)
・CASE
WHEN/THEN/ENDとセットなので、ここでは保留。
・SUBSTRING
文字列のうち次に指定する部分を抽出する。
・(TRIM(メールアドレス),
左右から空白を除去する。メールアドレスの列は 30桁のCHAR型(=固定長の文字列) だと定義されているので、その空白を除去するということ。
・LENGTH(TRIM(メールアドレス))-1, 2)
ここです。**ここがわからないのです。**p152の解説とその中の例題を見ても、「LENGTH」が「文字列の長さを取得する」「文字列の長さで絞込検索をする」ということしかわかりません。
「-1,2」が何を指すのかがわかりません。
もう少し詳しく見てみます。
問題文からすると、ここのコードは「メールアドレスの最後の2文字」を指しているはずです。
この部分だけ見ているとよくわからないので、もう一度SUBSTRINGまで戻ってみます。
p154でこう解説されていました。
SUBSTRING(文字列を表す列,抽出を開始する位置,抽出する文字の数)
⇒抽出された部分文字列
ということは、
「LENGTH(TRIM(メールアドレス))-1」 =抽出を開始する位置
「2」 =抽出する文字の数
ということでしょうか。ここで「2」の意味がわかりました。
あとは「LENGTH(TRIM(メールアドレス))-1」です。「-1」は何を指すのでしょうか?
「抽出を開始する位置」を指しているはずなのですが…
メールアドレスの末尾1文字目を「0」、2文字目を「-1」としているのでしょうか?
p155の例題を見ると「文字列の頭文字を1文字目」として扱っているのだと読み取れますが、
末尾の文字についてはどこにも触れられていませんでした。
見落としているのでしょうか?
「LENGTH -1 関数」等でググってみました。
→目ぼしい記事は見つからず。
本の中から「-」が入った構文を探してみます。
→p156にこんな構文が出てきました。
リスト5-13 百円単位の出金額を取得する
SELECT 出金額, ROUND(出金額, -2) AS 百円単位の出金額
FROM 家計簿
※解説:「これで、出金額の下2桁目、つまり10の位で四捨五入されることになるのよ。」
これだーーーーー!!!
やっとわかりました。
「-1」は「末尾1文字目」という意味だったのですね。
スッキリしました・・・。
文字数を「前から」数えていくのだと思い込んでいました。
「末尾1文字目から 2文字を 抽出する」
なんですね。「後ろから」数えるとのこと。やっとわかりました。
#まとめ
最後に整理します。
CASE ④SUBSTRING(①TRIM(メールアドレス),
②LENGTH(TRIM(メールアドレス))-1, ③2)
これは、
①メールアドレスの左右の空白を取り除いて、
②メールアドレスの末尾1文字目から
③2文字目までを
④抽出します
⑤その場合(→次のWHEN~に続く)
という意味だったのですね。
#さいごに
いき詰まっていましたが、Qiitaに書き出しながらひとつひとつを読み解くことで
無事にコードの意味を理解する事が出来ました。
終わってしまえば「なーんだ、そんなこと」なのですが、
記事を書いている最中は本当にわからない状態でした。
まだまだ序盤なのに時間をかけてしまい焦りますが、
ひとつひとつ進めていきたいと思います。
#参考
・書籍『スッキリわかるSQL入門第2版ドリル222問付き!』(インプレス)
#進捗記録
2020/9/15:データベースの学習スタート
2020/9/15~2020/9/21:『マンガでわかるデータベース』オーム社 / 1~4章(Qiita記事2本)
2020/9/22~:『スッキリわかるSQL入門第2版ドリル222問付き!』インプレス