试图找出一种有效的方法来选择跨多个表具有属性的记录。以下是基本设置:
structure
model
我的目标是输出侧院子中每一个玫瑰的列表,并显示颜色,但我仍然坚持select命令。如果我得到所有的工厂(p = Plant.all),我知道我可以很容易地用一个像<%= "#{p.name.common_name} in bed #{p.location.bed_name} has a color of #{p.color}" %>这样的语句来创建我的输出,如果我做两个连接,我就会看到更多我需要的记录和更长的搜索时间。举个例子-我有67朵玫瑰在16个不同的床,然而,我只有3朵玫瑰在旁边的院子。
我的直觉告诉我,我应该能够做到这样的事情:选择所有的植物名为玫瑰,然后从这个选择选择所有玫瑰在旁边的院子。
有人能帮我指出正确的方向吗?
发布于 2016-11-17 21:06:34
您可以将所有内容合并到一个查询中,如下所示:
Plant.joins(:name, :location).where(names: { common_name: "rose" }, locations: { bed_name: "side" })这会导致一个SQL查询,如下所示:
SELECT "plants".* FROM "plants" INNER JOIN "names" ON "names"."id" = "plants"."name_id" INNER JOIN "locations" ON "locations"."id" = "plants"."location_id" WHERE "names"."common_name" = 'rose' AND "locations"."bed_name" = 'side'请注意,您必须在where子句中使用复数表名,而在joins子句中使用单数关联名称。
假设您的表被正确地编入索引,即使使用巨大的表,这也几乎是瞬间运行的。
这是一个简单的例子,但您可以使用条件进行相当复杂的连接。详细信息可以在ActiveRecord文档中找到。
编辑
对于@Dan的评论,您可以通过使用includes预取连接中的关联数据来加快速度:
Plant.includes(:name, :location).where(names: { common_name: "rose" }, locations: { bed_name: "side" })这将同时从names和locations加载相关记录。includes可以方便地消除(或至少减少) N+1查询。它还足够聪明,可以知道何时可以检索单个查询中的所有数据,并在更有意义的时候返回到多个查询;您不必考虑它(尽管有时它会降低效率,因此,如果您认为日志会降低性能,请注意日志)。
在这种情况下,使用includes非常有效,从而产生一个包含关联数据的单个SQL查询:
SELECT "plants"."id" AS t0_r0, "plants"."color" AS t0_r1, "plants"."name_id" AS t0_r2, "plants"."location_id" AS t0_r3, "plants"."created_at" AS t0_r4, "plants"."updated_at" AS t0_r5, "names"."id" AS t1_r0, "names"."common_name" AS t1_r1, "names"."created_at" AS t1_r2, "names"."updated_at" AS t1_r3, "locations"."id" AS t2_r0, "locations"."bed_name" AS t2_r1, "locations"."created_at" AS t2_r2, "locations"."updated_at" AS t2_r3 FROM "plants" LEFT OUTER JOIN "names" ON "names"."id" = "plants"."name_id" LEFT OUTER JOIN "locations" ON "locations"."id" = "plants"."location_id" WHERE "names"."common_name" = 'rose' AND "locations"."bed_name" = 'side'https://stackoverflow.com/questions/40664644
复制相似问题