こんにちは!タクマです。
31歳未経験からエンジニア転職に成功し、
2021年3月より都内の受託開発企業にてサーバーサイドエンジニアとして働いており、
PHP/Laravelを使用し開発をしています。
今回はJOINの種類と違い、使い方について詳しく解説していきます。
joinとleftJoinの違いがわからない
joinの使い方がわからない
という方はこの記事を読めば全て解決しますので、ぜひ最後まで読んでください。
JOINとは
JOINとは複数のテーブルを一時的に一つのテーブルに結合することです。
ではどんな時に結合をするのかというと
- 欲しいデータが一つのテーブルからでは選択できない場合
- 欲しいデータが複数のテーブルに分散されている場合
などの場面が挙げられます。
JOINの種類
LaravelのJOINのメソッドは主に3種類あります。
- join(内部結合)
- leftJoin(左外部結合)
- rightJoin(右外部結合)
順番に一つずつ解説していきます。
joinメソッド
join
メソッドは複数のテーブルを内部結合するメソッドです。
例えば下のような二つのテーブルがあるとします。
Playersテーブル
id | name | team_id |
---|---|---|
1 | 吉田 | 7 |
2 | 村上 | 1 |
3 | 坂本 | 3 |
4 | 柳田 | 11 |
5 | 大野 | 4 |
6 | 山崎 | 6 |
Teamsテーブル
id | name |
---|---|
1 | ヤクルト |
2 | 阪神 |
3 | 巨人 |
4 | 中日 |
5 | 広島 |
6 | DeNA |
上の二つのテーブルをjoin
メソッドを使って内部結合する際は下記のように記述します。
$players = DB::table('players') // 主となるテーブル名
->select('players.id', 'players.name', 'teams.id as team_id', 'teams.name as team_name')
->join('teams', 'players.team_id', '=', 'teams.id') // 第一引数に結合するテーブル名、第二引数に主テーブルの結合キー、第四引数に結合するテーブルの結合キーを記述
->get();
$players
の中身は下のようになっています。
dd($players);
// 実行結果
Illuminate\Support\Collection {#306 ▼
#items: array:4 [▼
0 => {#1035 ▼
+"id": 2
+"name": "村上"
+"team_id": 1
+"team_name": "ヤクルト"
}
1 => {#313 ▼
+"id": 3
+"name": "坂本"
+"team_id": 3
+"team_name": "巨人"
}
2 => {#1101 ▼
+"id": 5
+"name": "大野"
+"team_id": 4
+"team_name": "中日"
}
3 => {#997 ▼
+"id": 6
+"name": "山崎"
+"team_id": 6
+"team_name": "DeNA"
}
]
}
テーブルで表すと下のようになります。
id | name | team_id | team_name |
---|---|---|---|
2 | 村上 | 1 | ヤクルト |
3 | 坂本 | 3 | 巨人 |
5 | 大野 | 4 | 中日 |
6 | 山崎 | 6 | DeNA |
このように結合条件に当てはまるものだけが抽出され結合されています。
これが内部結合です。
join
メソッドは最もよく使うJOIN系のメソッドになります。
ちなみに結合するテーブルそれぞれにカラム名が同じものがある場合(今回の例の場合id
とname
)、select()
メソッド内で取得するカラム名を変更しなければと右側のテーブル(主テーブルでない方)のデータに上書きされてしまうので注意が必要です。
下のようにselect()
がないと
$players = DB::table('players')
->join('teams', 'players.team_id', '=', 'teams.id')
->get();
下のようにplayersテーブルのid
とname
がteamsテーブルのid
とname
によって上書きされてしまいます。
dd($players);
// 実行結果
Illuminate\Support\Collection {#306 ▼
#items: array:4 [▼
0 => {#1191 ▼
+"id": 1
+"name": "ヤクルト"
+"team_id": 1
+"created_at": null
+"updated_at": null
}
1 => {#300 ▼
+"id": 3
+"name": "巨人"
+"team_id": 3
+"created_at": null
+"updated_at": null
}
2 => {#313 ▼
+"id": 4
+"name": "中日"
+"team_id": 4
+"created_at": null
+"updated_at": null
}
3 => {#997 ▼
+"id": 6
+"name": "DeNA"
+"team_id": 6
+"created_at": null
+"updated_at": null
}
]
}
そのため、カラム名が上書きされないよう、下記のようにselectメソッド内でカラム名を変更する必要があるのです。
// teamsテーブルのidをteam_idにというカラム名に変更
// teamsテーブルのnameカラムをteam_nameというカラム名に変更
select('players.id', 'players.name', 'teams.id as team_id', 'teams.name as team_name')
※上記はあくまで取得する際だけカラム名を変更しているだけであり、DBのカラム名が変更されている訳ではありません。
leftJoinメソッド
leftJoin
メソッドは複数のテーブルを左外部結合するメソッドです。
書き方はjoin
と変わりません。
$players = DB::table('players') // 主となるテーブル名
->select('players.id', 'players.name', 'teams.id as team_id', 'teams.name as team_name')
->leftJoin('teams', 'players.team_id', '=', 'teams.id') // 第一引数に結合するテーブル名、第二引数に主テーブルの結合キー、第四引数に結合するテーブルの結合キーを記述
->get();
$players
の中身は下記のようになっています。
dd($players);
// 実行結果
Illuminate\Support\Collection {#306 ▼
#items: array:6 [▼
0 => {#1035 ▼
+"id": 1
+"name": "吉田"
+"team_id": null
+"team_name": null
}
1 => {#313 ▼
+"id": 2
+"name": "村上"
+"team_id": 1
+"team_name": "ヤクルト"
}
2 => {#1101 ▼
+"id": 3
+"name": "坂本"
+"team_id": 3
+"team_name": "巨人"
}
3 => {#997 ▼
+"id": 4
+"name": "柳田"
+"team_id": null
+"team_name": null
}
4 => {#300 ▼
+"id": 5
+"name": "大野"
+"team_id": 4
+"team_name": "中日"
}
5 => {#1100 ▼
+"id": 6
+"name": "山崎"
+"team_id": 6
+"team_name": "DeNA"
}
]
}
テーブルで表すと下のようになります。
id | name | team_id | team_name |
---|---|---|---|
1 | 吉田 | null | null |
2 | 村上 | 1 | ヤクルト |
3 | 坂本 | 3 | 巨人 |
4 | 柳田 | null | null |
5 | 大野 | 4 | 中日 |
6 | 山崎 | 6 | DeNA |
結果はjoin
(内部結合)の時とは違い、主テーブルのデータがID順に全て出力されています。
左外部結合とは、主テーブルのデータを結合しなかったデータも含めて全て出力することになります。
これがleftJoin
メソッドです。
rightJoinメソッド
rightJoin
メソッドは複数のテーブルを右外部結合するメソッドです。
こちらも書き方はjoin
と変わりません。
$players = DB::table('players') // 主となるテーブル名
->select('players.id', 'players.name', 'teams.id as team_id', 'teams.name as team_name')
->rightJoin('teams', 'players.team_id', '=', 'teams.id') // 第一引数に結合するテーブル名、第二引数に主テーブルの結合キー、第四引数に結合するテーブルの結合キーを記述
->get();
$players
の中身は下記のようになっています。
dd($players);
// 実行結果
Illuminate\Support\Collection {#306 ▼
#items: array:6 [▼
0 => {#1035 ▼
+"id": 2
+"name": "村上"
+"team_id": 1
+"team_name": "ヤクルト"
}
1 => {#313 ▼
+"id": null
+"name": null
+"team_id": 2
+"team_name": "阪神"
}
2 => {#1101 ▼
+"id": 3
+"name": "坂本"
+"team_id": 3
+"team_name": "巨人"
}
3 => {#997 ▼
+"id": 5
+"name": "大野"
+"team_id": 4
+"team_name": "中日"
}
4 => {#300 ▼
+"id": null
+"name": null
+"team_id": 5
+"team_name": "広島"
}
5 => {#1100 ▼
+"id": 6
+"name": "山崎"
+"team_id": 6
+"team_name": "DeNA"
}
]
}
テーブルで表すと下のようになります。
id | name | team_id | team_name |
---|---|---|---|
2 | 村上 | 1 | ヤクルト |
null | null | 2 | 阪神 |
3 | 坂本 | 3 | 巨人 |
5 | 大野 | 4 | 中日 |
null | null | 5 | 広島 |
6 | 山崎 | 6 | DeNA |
結果はjoin
(内部結合)やleftJoin
(左外部結合)の時とは違い、主テーブルでない方のデータがID順に全て出力されています。
右外部結合とは、主テーブルでない方のデータを結合しなかったデータも含めて全て出力することになります。
これがrightJoin
メソッドです。
ちなみにleftJoinとrightJoinどちらを使うべきかという点が気になるかと思いますが、一般的にはleftJoin
を使うことの方が多いようです。
さいごに
いかがでしたでしょうか?
3つのJOINの違いついて理解できましたでしょうか?
ご質問やご指摘等ある方はコメントしていただければ返信させていただきます。
これからもLaravelエンジニアの方、Laravel学習中の初学者の方に役に立つ記事を更新していきますのでよろしくお願いします!
Twitterでも情報発信をしていますので、よかったらフォローをお願いします(^^)