💻
Active Recordのjoinsメソッドで複数テーブルを結合する
これは何?
RailsガイドのActive Record クエリインターフェイス / 13.1.3 複数の関連付けを結合するを読んでいて、joinsメソッド
で配列とハッシュをどのように使えばいいか深く知りたくなった
ので、いくつかのテーブル構成で実際に試し、結果をまとめた記事です。
対象バージョン
- ruby:
2.7.6
- rails:
7.0.3.1
joinsメソッド内のルール
①複数のテーブルを結合する場合は、配列[]
にする
②親テーブルに対して複数のテーブルを結合する場合は、配列[]
を省略できる
③ネストして結合する場合は、ハッシュ{}
にする
④親テーブルに対して結合するテーブルが全てネストしている場合は、ハッシュ{}
を省略できる
⑤結合するテーブルが全てネストしている場合はハッシュ{}
をまとめることができる
実例
対象のテーブル構成
- A
- B
- C
- D
- E
- F
- G
- H
- I
- インデントで親子関係を表現しており、それぞれのテーブルは
1:1
の想定です。 - 最終的には、上記のテーブル構成に対して、
joinsメソッド
のみで結合することを目指します。
例1
対象のテーブル構成
- A
- B
- G
実装方法
# ルール①を適用
A.joins([:b, :g])
# ルール②を適用
A.joins(:b, :g)
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN gs ON gs.a_id = as.id
例2
対象のテーブル構成
- A
- B
- C
実装方法
# ルール③を適用
A.joins({b: :c})
# ルール④を適用
A.joins(b: :c)
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
例3
対象のテーブル構成
- A
- B
- C
- G
実装方法
# 例2に対して、ルール①を適用
A.joins([{b: :c}, :g])
# ルール②を適用
A.joins({b: :c}, :g)
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
INNER JOIN gs ON gs.a_id = as.id
例4
対象のテーブル構成
- A
- B
- C
- G
- H
実装方法
# 例3に対して、ルール③を適用
A.joins([{b: :c}, {g: :h}])
# ルール②を適用
A.joins({b: :c}, {g: :h})
# ルール⑤を適用
A.joins({b: :c, g: :h})
# ルール④を適用
A.joins(b: :c, g: :h)
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
INNER JOIN gs ON gs.a_id = as.id
INNER JOIN hs ON hs.g_id = gs.id
例5
対象のテーブル構成
- A
- B
- C
- F
- G
- H
実装方法
# 例4に対して、ルール①を適用
A.joins([{b: [:c, :f]}, {g: :h}])
# ルール②を適用
A.joins({b: [:c, :f]}, {g: :h})
# ルール⑤を適用
A.joins({b: [:c, :f], g: :h})
# ルール④を適用
A.joins(b: [:c, :f], g: :h)
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
INNER JOIN fs ON fs.b_id = bs.id
INNER JOIN gs ON gs.a_id = as.id
INNER JOIN hs ON hs.g_id = gs.id
例6
対象のテーブル構成
- A
- B
- C
- F
- G
- H
- I
実装方法
# 例5に対して、ルール①を適用
A.joins([{b: [:c, :f]}, {g: [:h, :i]}])
# ルール②を適用
A.joins({b: [:c, :f]}, {g: [:h, :i]})
# ルール⑤を適用
A.joins({b: [:c, :f], g: [:h, :i]})
# ルール④を適用
A.joins(b: [:c, :f], g: [:h, :i])
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
INNER JOIN fs ON fs.b_id = bs.id
INNER JOIN gs ON gs.a_id = as.id
INNER JOIN hs ON hs.g_id = gs.id
INNER JOIN is ON is.g_id = gs.id
例7
対象のテーブル構成
- A
- B
- C
- D
- F
- G
- H
- I
実装方法
# 例6に対して、ルール③を適用
A.joins([{b: [{c: :d}, :f]}, {g: [:h, :i]}])
# ルール②を適用
A.joins({b: [{c: :d}, :f]}, {g: [:h, :i]})
# ルール⑤を適用
A.joins({b: [{c: :d}, :f], g: [:h, :i]})
# ルール④を適用
A.joins(b: [{c: :d}, :f], g: [:h, :i])
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
INNER JOIN ds ON ds.c_id = cs.id
INNER JOIN fs ON fs.b_id = bs.id
INNER JOIN gs ON gs.a_id = as.id
INNER JOIN hs ON hs.g_id = gs.id
INNER JOIN is ON is.g_id = gs.id
例8
対象のテーブル構成
- A
- B
- C
- D
- E
- F
- G
- H
- I
実装方法
# 例7に対して、ルール①を適用
A.joins([{b: [{c: [:d, :e]}, :f]}, {g: [:h, :i]}])
# ルール②を適用
A.joins({b: [{c: [:d, :e]}, :f]}, {g: [:h, :i]})
# ルール⑤を適用
A.joins({b: [{c: [:d, :e]}, :f], g: [:h, :i]})
# ルール④を適用
A.joins(b: [{c: [:d, :e]}, :f], g: [:h, :i])
発行されるSQL
SELECT
as.*
FROM
as
INNER JOIN bs ON bs.a_id = as.id
INNER JOIN cs ON cs.b_id = bs.id
INNER JOIN ds ON ds.c_id = cs.id
INNER JOIN es ON es.c_id = cs.id
INNER JOIN fs ON fs.b_id = bs.id
INNER JOIN gs ON gs.a_id = as.id
INNER JOIN hs ON hs.g_id = gs.id
INNER JOIN is ON is.g_id = gs.id
Discussion