多対多のDBテーブルでJOINを実際に試す

2020/09/07 04:24

DBテーブルのJOINを、実際にありそうな多対多の構造のテーブルで試してみました。簡単なJOINの動作や考え方の確認、WHEREによる絞り込みやGROUP BYによる集計まで「JOINをどのように使って何ができるのかのイメージ」を確認して、後半ではINNER JOINとLEFT JOINの違いまで見ています。JOINの概要は20分程度、JOINの種類は15分未満の動画です。

JOINでテーブルの結合ができます

JOINはデータベースのテーブルを結合する機能です。結合したあとは「大きな一個のテーブルがある」というような概念で一つのテーブルと同様に操作ができます。RDB(MySQLやPostgreSQLなど)ではこのJOINが可能な前提でテーブルを分割して正規化していくので、重要な機能です。

サンプルとして DBテーブルの多対多で解説した users/members/clubs のテーブルを用意して行っています。

JOINはテーブルを分割すると数多く発生するので、多対多のリレーションシップを作ったりすると大抵一緒に必要になります。

よく使うJOIN

実際に開発でよく使うのは以下の2つだと思います。LEFTがあるのでもちろんRIGHT OUTER JOINもありますが、大抵の場合中心にしたいものを先に書く結果として左に寄っているため、LEFT OUTER JOINする方が圧倒的に多いでしょう。

INNER JOIN(内部結合)

結合される両者のテーブルが条件を満たせる場合にレコードが残ります。例えば結合される相手のレコードが見つからない場合、結合後のレコードには存在しなくなります(2番目の動画の鈴木さんの状態)。

単純にJOINとだけ書いてもこの意味合いになります。

LEFT OUTER JOIN(左外部結合)

通常先に書いたテーブル名が左に置かれているというようなイメージで左のレコードを維持しつつもう片方のテーブルを結合していきます。基本の動きはINNER JOINと同じ結果になりますが、結合される相手のテーブルが見つからない場合、左のテーブルの項目は残し、結合相手がいない場所はNULLで埋まります。

OUTERが略せるので、JEFT JOINとも書けます。

ちょっと複雑なJOINをする時のコツ

SELECTで絞る前にJOINだけして SELCT * で「JOINの結果どんな巨大なテーブルができたか」を一度確認したりします。こうすると今扱っているデータの全体像が見えやすいです。そのあと WHERE や GROUP BY で絞り込んだり集計したりしていくと混乱せずに進められる事が多いはずなので参考にしてください。

そのほか出てきた構文

ここではザッとの紹介です(機会があればそれぞれ細かくやるかもしれません)。

  • WHERE: 条件をつけて絞り込みを行います。
  • AS: SELECT の中で使用して、別名を付けます。
  • GROUP BY: 指定したカラムを基準に複数のレコードをひとまとめにします。
  • IS NULL: 値が NULL かどうか判断します。
  • CASE: 条件に従って、結果を分岐して取得できます。

N+1問題

DBの検索件数が爆発的に増えてしまう問題です。最初の一回で複数のレコードを検索したあと(ここで一回の検索でN個のレコードが返ってくる)、そのそれぞれに対して一回ずつ検索する(N回の続きの検索をする)事で起きます。

JOINはN+1問題の一つの解決方法です(他にもあります)。

「JOINなどしなくてもデータを1件ずつ取ってくれば良いのでは?」

大抵の場合においてNOです。SQLの発行回数はシステムのパフォーマンスに大きく影響するので、できるなら回数を減らして性能を上げたいと思うことの方が多いです。例えば100件の情報を取得しようとした時に、100回以上SQLの発行が発生する(先述のN+1問題がまさにその状況です)ような状況はなるべく避けたいのです。

また、WHEREによる絞り込みを避けて全部取得してきてからIF文で判断するようなコードもシステムのメモリに大きな負荷をかける可能性が高いので、なるべく避けたいです。WHEREで絞れるだけ絞ってから対応するのが良いです。

この記事を書いた人

佐藤 正志

サークルアラウンド株式会社 代表取締役