クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

JOINで2つの表をつなぐ方法

このレッスンのあとで: 2つの表を、JOIN でつなげられる。

50分のレッスンコマンド5件MySQL と phpMyAdmin のラボ:ショップのデータベースで SQL を練習する

注文画面に商品名が出る理由

SQLの JOIN は、外部キーでつながった2つの表を、1つの結果にまとめる命令です。商品と、その商品のカテゴリ名を1つの表のように読めます。

ネットショップの注文表には、商品の番号しか入っていません。それでも画面に商品名が出るのは、裏で JOIN が表をつないでいるからです。

このレッスンのゴール

メモ

2つの表を、JOIN でつなげられる。

キーワード

ことばいみれい
外部キー別の表の行を指す列club_id
JOIN2つの表を、同じ値の列でつなぐ操作
ONどの列と列が同じなら、つなぐかを決める句
別名(エイリアス)表や列に付ける短い呼び名AS club
INNER JOIN相手の行がある行だけを残すつなぎ方
LEFT JOIN左の表の行を、相手がなくても残すつなぎ方

学生が入力するセルは、このプレビューでは空白です。

なぜ表を分けるのか

部員の表に、部活の名前と部屋を毎回書くと、同じ文字が何十回も並びます。部屋が変わったら、何十行も直すことになります。

だから、部活は部活の表に1行だけ置き、部員の表には部活の番号(外部キー)だけを入れます。読むときに、JOIN でつなぎ直します。

例: 分けた2つの表

members の idnameclub_id指す clubs の行
1田中1サッカー部(グラウンド)
2佐藤2美術部(美術室)
5伊藤NULLどの部活も指さない

学生が入力するセルは、このプレビューでは空白です。

試す: 部員と部活をつなぐ

コード: sql
-- 部員と、その部員の部活の名前を並べます。
SELECT members.name, clubs.name AS club
FROM members
JOIN clubs ON members.club_id = clubs.id
ORDER BY members.id;
-- 伊藤さん(部活なし)が出ないことを確かめましょう。

JOIN と ON の書き方

FROM members JOIN clubs ON members.club_id = clubs.id と書きます。ON の右には、つなぐ列どうしの等式を置きます。

2つの表に同じ名前の列(name)があるときは、clubs.name のように、表の名前を前に付けます。長いときは AS で別名を付けます。

始める前に

メモ

上のバーの Start the lab を押し、マシンが動き出すまで待ってください。ターミナルを開き直したときは、最初の2つの Run をもう一度押します。

証明書を受け入れる設定

コマンド
printf '[client]\nssl-verify-server-cert=0\n' > ~/.my.cnf

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ショップ用の短い名前

コマンド
alias sql='mariadb -h db -u student -pstudent shop -t -e'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

商品とカテゴリの名前

コマンド
sql "SELECT p.name AS product, c.name AS category FROM products p JOIN categories c ON c.id = p.category_id ORDER BY p.id LIMIT 8"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

表にも別名を付けられる

上の Run では、products p のように、表に短い別名を付けました。以降は p.name と書けます。

別名は書く量を減らし、どの表の列かをはっきりさせます。結果の列には AS で、読みやすい題を付けられます。

商品と仕入れ先の町

コマンド
sql "SELECT p.name, s.city FROM products p JOIN suppliers s ON s.id = p.supplier_id WHERE s.country = 'Japan' ORDER BY p.id"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

相手のいない行はどうなるのか

普通の JOIN(INNER JOIN)は、相手がいる行だけを返します。部活のない部員は、結果から消えます。

消したくないときは LEFT JOIN を使います。左の表の行は全部残り、相手がいない列は NULL になります。

試す: 部活のない部員も残す

コード: sql
-- 部活のない部員も残します。
SELECT members.name, clubs.name AS club
FROM members
LEFT JOIN clubs ON members.club_id = clubs.id
ORDER BY members.id;
-- 部員が1人もいない部活を探すには、表の順番をどう変えますか。

カテゴリのない商品

コマンド
sql "SELECT p.name FROM products p LEFT JOIN categories c ON c.id = p.category_id WHERE c.id IS NULL ORDER BY p.name"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

ON を書き忘れると、2つの表の全部の組み合わせが返ります。表が100行と200行なら、2万行です。結果が多すぎたら、まず ON を確かめます。

例: 2つのつなぎ方の違い

書き方相手がいない行は部員8人の例の行数
JOIN(INNER JOIN)消える7行
LEFT JOIN残り、相手の列は NULL8行

学生が入力するセルは、このプレビューでは空白です。

さらに挑戦: 部員のいない部活

ショップで、レビューが1件もない商品を探します。products を左、reviews を右にして LEFT JOIN し、reviews.id IS NULL の行を残します。

このクエリを書き、結果の件数を数えてください。なぜ reviews.product_id IS NULL でも同じ結果になるかを、一言で説明してください。

このラボとソースについて: MySQL と phpMyAdmin のラボ:ショップのデータベースで SQL を練習する

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。