![](https://b3s.be-s.co.jp/wp-content/uploads/2022/06/laravel_doc.png)
雑記
LaravelのJoinを通じてRDBテーブルの結合を理解しよう!
edy
公開日:2022/06/22
LaravelのJoinを通じてRDBテーブルの結合を理解しよう!
この記事では、次の事を記載しています。
目次
- 1. 背景
- 2. サンプル画面
- 2.1. テーブル設計
- 2.2. 処理
- 3. SQLでどうやる?
- 3.1. 画面表示
- 3.2. 更新対象データの取得
- 4. まとめ
1.背景
MongoDBなどのNoSQLを使うケースも多くなましたが、まだまだRDB(リレーショナル・データベース)を扱う機会は多いです。特に業務系システムは。
そこで今回はRDBの結合についてポイントをおさらいします。
ついでにLaravelで結合をすっきりコーディングする方法がありますので紹介します。
2.サンプル画面
説明のため、以下のようなサンプル画面を開発することになったと想像してください。
従業員が、自分の作業実績を1週間分を1日1行で入力する画面です。
画面表示時に、年度、週番号、ユーザーIDをキーにして該当画面を表示します。
この画面で扱うデータを取得する際、テーブル結合します!では見ていきましょう。
2.1.テーブル設計
テーブルは次の2つを設計しました。
・カレンダーマスタテーブル
1年365日行のデータが登録されています。週番号列を持っており、週番号を指定することで週ごとのデータを絞り込めます。
・稼働実績テーブル
ユーザー毎の1日1行の稼働実績データが登録されています。
2.2.処理
画面表示や更新の際、テーブルデータをどのように取得しますか?
もちろんSQLで結合しますよね!
3.SQLでどうやる?
ご存知の通りRDBのテーブルデータを取得するにはSQLを使います。
ここでは、画面表示時と、更新前データ取得時のSQLで考えてみます。
3.1.画面表示
SQLの内容
週番号とユーザーを指定して、1週間分のデータを取得します。
既に、ユーザーの作業実績が登録してあれば、作業時間も表示します。
1 2 3 4 5 6 7 8 |
SELECT 年,月,日,週番号,作業時間,コメント FROM カレンダーマスタ AS c LEFT OUTER JOIN 稼働実績 AS rd ON c.年 = rd.年 AND c.月 = rd.月 AND c.日 = rd.日 AND rd.ユーザー = 寺門 WHERE c.週番号 = 22 |
ポイント
カレンダーマスタテーブルと稼働実績テーブルを結合します。
カレンダーマスタのデータは必ず取得し、稼働実績テーブルはデータがあれば結合して取得するSQLです。
外部結合といい、LEFT OUTER JOINを使います。
結合の左側テーブル(カレンダーマスタ)に対して、結合の右側テーブル(稼働実績)はデータが無い場合、以下の様に取得できます。
結合の左側テーブル(カレンダーマスタ)に対して、結合の右側テーブル(稼働実績)はデータがある場合、以下の様に取得できます。
上記の場合の左側テーブルは必ずデータ取得するので、軸テーブルと呼ぶ場合もあります。
Laravelでの書き方
LaravelのドキュメントにAdvanced Joinというものがあります。
これにならって、上記のSQLを見やすく記載すると、以下のようになります。
カレンダーマスタと稼働実績の結合条件のみをjoin関数の波括弧の中にまとめて記載できます。赤枠で囲われた箇所。
カレンダーマスタのみ抽出条件は、別途where関数に記述できるので、結合条件がスッキリと記載できました!
3.2.更新対象データの取得
SQLの内容
該当ユーザーの稼働実績データを取得します。
画面に表示した週のデータのみに絞り込みたいので、カレンダーマスタを結合します。
1 2 3 4 5 6 7 8 |
SELECT 年,月,日,週番号,作業時間,コメント FROM 稼働実績 AS rd JOIN カレンダーマスタ AS c ON c.年 = rd.年 AND c.月 = rd.月 AND c.日 = rd.日 AND c.週番号 = 22 WHERE rd.ユーザー = 寺門 |
ポイント
カレンダーマスタテーブルと稼働実績テーブルを結合します。
稼働実績テーブル、カレンダーマスタともに結合して両方テーブルのデータを必ず取得するSQLです。
等価結合といい、JOINまたは、INNER JOINを使います。
結合の左側テーブル(稼働実績)に対して、結合の右側テーブル(カレンダーマスタ)はデータが無い場合、取得されません。
5/31のデータはカレンダーマスタに存在しますが、稼働実績に存在しないため、取得されません。
Laravelでの書き方
Laravelの書き方で上記のSQLを見やすく記載すると、以下のようになります。
稼働実績とカレンダーマスタの結合条件はjoin関数となります。
3.3.その他
必要ではないのに外部結合することは絶対に避けなければいけません。
例えば、第22週で、実績が入っている日のデータを取得しようと思って、以下のSQLを記述したとします。
結果はどうなるでしょうか?
1 2 3 4 5 6 7 |
SELECT 年,月,日,週番号,作業時間,コメント FROM カレンダーマスタ AS c LEFT OUTER JOIN 稼働実績 AS rd ON c.年 = rd.年 AND c.月 = rd.月 AND c.日 = rd.日 WHERE c.週番号 = 22 |
結合テーブルの稼働実績は、複数ユーザーが稼働実績を登録していた場合、カレンダーマスターが複数行となって取得されます。
6/1のデータがそれです。こういった取得は意図しないことが多いのではないでしょうか。
注意すべきポイントとしては、「外部結合は、条件によっては軸テーブルのデータも増加する」ということです。
SQL実行して思ったより結果が多いなどの場合、このケースになってる可能性があります。
4.まとめ
RDBの、結合・外部結合の違いをまとめてみました。
Web・システムエンジニアにとっては必須の知識です。
自己チェックしてみてください。