Laravel

Laravel join / leftJoin / rightJoinの違いと使い方について解説

タクマ

こんにちは!タクマです。

31歳未経験からエンジニア転職に成功し、

2021年3月より都内の受託開発企業にてサーバーサイドエンジニアとして働いており、

PHP/Laravelを使用し開発をしています。

今回はJOINの種類と違い、使い方について詳しく解説していきます。

joinとleftJoinの違いがわからない

joinの使い方がわからない

という方はこの記事を読めば全て解決しますので、ぜひ最後まで読んでください。

JOINとは

JOINとは複数のテーブルを一時的に一つのテーブルに結合することです。

ではどんな時に結合をするのかというと

  • 欲しいデータが一つのテーブルからでは選択できない場合
  • 欲しいデータが複数のテーブルに分散されている場合

などの場面が挙げられます。

JOINの種類

LaravelのJOINのメソッドは主に3種類あります。

  • join(内部結合)
  • leftJoin(左外部結合)
  • rightJoin(右外部結合)

順番に一つずつ解説していきます。

joinメソッド

joinメソッドは複数のテーブルを内部結合するメソッドです。

例えば下のような二つのテーブルがあるとします。

Playersテーブル

idnameteam_id
1吉田7
2村上1
3坂本3
4柳田11
5大野4
6山崎6

Teamsテーブル

idname
1ヤクルト
2阪神
3巨人
4中日
5広島
6DeNA

上の二つのテーブルを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"
    }
  ]
}

テーブルで表すと下のようになります。

idnameteam_idteam_name
2村上1ヤクルト
3坂本3巨人
5大野4中日
6山崎6DeNA

このように結合条件に当てはまるものだけが抽出され結合されています。

これが内部結合です。

joinメソッドは最もよく使うJOIN系のメソッドになります。

ちなみに結合するテーブルそれぞれにカラム名が同じものがある場合(今回の例の場合idname)、select()メソッド内で取得するカラム名を変更しなければと右側のテーブル(主テーブルでない方)のデータに上書きされてしまうので注意が必要です。

下のようにselect()がないと

$players = DB::table('players')
    ->join('teams', 'players.team_id', '=', 'teams.id')
    ->get();

下のようにplayersテーブルのidnameがteamsテーブルのidnameによって上書きされてしまいます。

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"
    }
  ]
}

テーブルで表すと下のようになります。

idnameteam_idteam_name
1吉田nullnull
2村上1ヤクルト
3坂本3巨人
4柳田nullnull
5大野4中日
6山崎6DeNA

結果は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"
    }
  ]
}

テーブルで表すと下のようになります。

idnameteam_idteam_name
2村上1ヤクルト
nullnull2阪神
3坂本3巨人
5大野4中日
nullnull5広島
6山崎6DeNA

結果はjoin(内部結合)やleftJoin(左外部結合)の時とは違い、主テーブルでない方のデータがID順に全て出力されています。

右外部結合とは、主テーブルでない方のデータを結合しなかったデータも含めて全て出力することになります。

これがrightJoinメソッドです。

ちなみにleftJoinとrightJoinどちらを使うべきかという点が気になるかと思いますが、一般的にはleftJoinを使うことの方が多いようです。

さいごに

いかがでしたでしょうか?

3つのJOINの違いついて理解できましたでしょうか?

ご質問やご指摘等ある方はコメントしていただければ返信させていただきます。

これからもLaravelエンジニアの方、Laravel学習中の初学者の方に役に立つ記事を更新していきますのでよろしくお願いします!

Twitterでも情報発信をしていますので、よかったらフォローをお願いします(^^)

Webエンジニア
タクマ
埼玉県出身の31歳

30歳からプログラミングを始め31歳でWebエンジニアに転職成功。

現在は都内の受託開発企業にてサーバーサイドエンジニアをしています。

\ Follow me /

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA