ここでは、初心者から実践的に学べるプログラミングスクール「ウェブカツ!!」のPHP・MySQL部入門またはWEBサービス部を受講している生徒の方向けに、さらに「SQL」についての理解度を上げるため特訓をしていきます。
ここからは、WEBサービス部で初めて出てくる内容を元に特訓をするので、まだWEBサービス部を1周見ていない人は見てからにしてください。
出題の回答は全て「SQL言語」を使って答えてください。
DBソフトの種類によってSQL言語は微妙に違いますが(と言っても基本の書き方はどれも同じなのでどのDBでも使える知識です)、ここでは「MySQL」を元にしたSQLの書き方を特訓していきます。
必ず実際にMySQLを動かしてphpMyAdminから問題のテーブルを作成してSQLを実行(「SQL」というタブから行えます)しましょう。(じゃないと練習にならないので)
鬼練14:結合したい!
結合したいんですよ。いや、いやらしい意味じゃなく。
仕様書
下記要件に従ってSQLを記述してください。
下記の構造のテーブル「users」「products」をphpMyAdminから作成し、そのテーブルにレコードを入れてください
挿入するデータは下記の5つです。
○users1つ目のデータ
id:連番(1)
name:ウェブカツおじさん
email:test@test.com
gender:1
○users2つ目のデータ
id:連番(2)
name:筋トレおじさん
email:test@test.com
gender:1
○products1つ目のデータ
id:連番(1)
user_id:2
name:プロテイン
detail:ホエイプロテインです。筋肉の生成に必要なものです。
○products2つ目のデータ
id:連番(2)
user_id:2
name:HMB
detail:HMBは筋肉の生成を促進します。プロテインと併用すると効果的です。プロテインを摂取せずにHMBを摂るだけでも筋肉はついていきます。
○products3つ目のデータ
id:連番(3)
user_id:3
name:ダンベル
detail:ダンベルはトレイニーには必須の器具です。挙げてもよし。振ってもよし。
としてください。
上記データから
ユーザーIDが2と3のユーザーのユーザー情報と商品テーブルのレコードとカラムを「全て」
取得してください。
また、
ユーザーがいない場合も商品情報を取得してください。
ヒント
片方のレコードがなくても取得するってやつですね。
実は、これ出来ません。
商品テーブルの「外部キー制約」を外さないとそもそも「存在しないユーザー」の商品情報なんて登録出来ないからです。
試しにINSERT文で入れてみてください。エラーになるので。(ちなみに「挿入」タブからやろうとするとuser_idカラムには、そもそも存在するユーザーしか選択できなくなってます)
なので、外部キー制約は外して試してみましょう。
答え
では、SQL文の答えです。
1 |
SELECT * FROM users RIGHT JOIN products ON users.id = products.user_id WHERE user_id = 2 OR user_id = 3 |
こうですね。
ユーザー情報がなかったとしても、対象の商品テーブルの情報は取得したい。
わけなので、こうなりますね。
ちなみにテーブルを逆にしても書けます。
1 |
SELECT * FROM products LEFT JOIN users ON users.id = products.user_id WHERE user_id = 2 OR user_id = 3 |
これも同じ意味ですね。
ただし、微妙な違いがあって、試してもらうと分かりますが、
テーブルが結合されてどっちのテーブルのカラムが先にくるか?で違いがあります。
でも、結局取得した順番はサービスの中で実際に表示する時などまず関係ないので、どっちでもいいでしょう。
さらにこんな書き方も出来ます。
1 |
SELECT * FROM users AS u RIGHT JOIN products AS p ON u.id = p.user_id WHERE user_id = 2 OR user_id = 3 |
「AS句」というものを使って、
テーブルだったりカラム名に「別名」をつけられます。
そうすれば、SQLも毎回「usersの〜」って書かなくていいんですね。
「u.id」とやれば「usersテーブルのid」という意味になります。
大抵、SQLを結合するときはこのAS句を使います。
さらには、
1 |
WHERE p.user_id = 2 OR p.user_id = 3 |
という形で後ろも書いてあげましょう。
今回、user_idカラムというのはproductsテーブルにしかないので、カラム名だけの指定でDBさんには伝わりますが、
各テーブルに同じカラム名がある場合はどっちのカラムの事を言っているのかちゃんと伝えなきゃいけません。
いちいちそういうのを調べてつけるつけないやってるよりは一切合切つけちゃいましょう。
ちなみに前の結合もそうなんですが、そのまんまじゃ実はデータとして使いもんになりません。
なぜだか分かりますか?
それは、
カラム名「name」や「id」がダブっている。
ってことです。
実際にこのDBを元にPHPなどであれば
1 |
echo $productDetails['name']; |
みたいなイメージで取り出して使うことになりますが、
どっちのname?
ってなりますよね。
実際には、SELECT文使う時には取得するカラム名を一つ一つ指定する事がほとんどなので、
1 |
SELECT u.id, u.name AS username, u.email, u.gender, p.id AS product_id, p.user_id, p.name AS product_name, p.detail FROM users AS u RIGHT JOIN products AS p ON u.id = p.user_id WHERE user_id = 2 OR user_id = 3 |
みたいにカラムにまた別名をつけてあげる事で取得したデータのカラムが別名で取得できるので、あとは
1 |
echo $productDetails['product_name']; |
のようにその別名を指定すればデータが取れます。