据我所知,Rails执行LEFT JOIN
的唯一方法是手动编写SQL,如下所示:
Company.joins('LEFT JOIN people ON companies.id = people.company_id')
但是,加入其他表并使用.includes(:people)
变得非常棘手。
我需要使用.includes(:people)
,因为每当我访问people
方法时,Rails都会生成额外的数据库请求(相关问题:When joining table, rails anyway makes additional request when accessing fields from joined table)
所以,这有效:
Company.joins('LEFT JOIN people ON companies.id = people.company_id')
这有效:
Company.joins('LEFT JOIN people ON companies.id = people.company_id')
.includes(:people)
这有效:
Company.joins('LEFT JOIN people ON companies.id = people.company_id')
.includes(:people).joins(:city)
不起作用:
Company.joins('LEFT JOIN people ON companies.id = people.company_id')
.includes(:people).joins(:city).includes(:city)
最终加入people
两次,当然db抱怨模糊列名称:people.id
。
生成的SQL是:
SELECT "companies"."id" AS t0_r0, "companies"."title" AS t0_r1,
"companies"."address" AS t0_r2, "companies"."city_id" AS t0_r3,
"companies"."created_at" AS t0_r4, "companies"."updated_at" AS t0_r5,
"people"."id" AS t1_r0, "people"."name" AS t1_r1, "people"."surname" AS t1_r2,
"people"."patronymic" AS t1_r3, "people"."company_id" AS t1_r4,
"people"."created_at" AS t1_r5, "people"."updated_at" AS t1_r6,
"cities"."id" AS t2_r0, "cities"."title" AS t2_r1, "cities"."created_at" AS t2_r2,
"cities"."updated_at" AS t2_r3, "cities"."test" AS t2_r4 FROM "companies"
INNER JOIN "cities" ON "cities"."id" = "companies"."city_id"
LEFT OUTER JOIN "people" ON "people"."company_id" = "companies"."id"
LEFT JOIN people ON companies.id = people.company_id
我的理解是,当我们手动编写JOIN
SQL代码时,Rails无法控制它,并且它无法确定people
表已经加入。
如果我这样写,它就有效:
Company.joins(:people).includes(:people).joins(:city).includes(:city)
但是,它使用INNER JOIN
,但我需要LEFT JOIN
。我仍然无法找到使用LEFT JOIN
的方法,以便在Rails的控制之下。
怎么做?
答案 0 :(得分:5)
知道了:我们需要将.references()
与.includes
结合使用;然后,Rails执行LEFT JOIN
,我们可以在SQL查询中引用连接表。
所以,这有效:
Company.includes(:people).references(:people).includes(:city).references(:city)
嗯,这看起来很混乱。