首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Rails4中跨多个表构建高效的select命令?

如何在Rails4中跨多个表构建高效的select命令?
EN

Stack Overflow用户
提问于 2016-11-17 20:44:01
回答 1查看 30关注 0票数 2

试图找出一种有效的方法来选择跨多个表具有属性的记录。以下是基本设置:

structure

  • 植物(字段: id,name_id,location_id,颜色)(1000个记录)
  • 名称(字段: id,Common_name) (50条记录)
  • 位置(字段: id,Bed_name) (125个记录)

model

  • 植物- belongs_to名称,belongs_to位置
  • 名称- has_many植物
  • 位置- has_many工厂

我的目标是输出侧院子中每一个玫瑰的列表,并显示颜色,但我仍然坚持select命令。如果我得到所有的工厂(p = Plant.all),我知道我可以很容易地用一个像<%= "#{p.name.common_name} in bed #{p.location.bed_name} has a color of #{p.color}" %>这样的语句来创建我的输出,如果我做两个连接,我就会看到更多我需要的记录和更长的搜索时间。举个例子-我有67朵玫瑰在16个不同的床,然而,我只有3朵玫瑰在旁边的院子。

我的直觉告诉我,我应该能够做到这样的事情:选择所有的植物名为玫瑰,然后从这个选择选择所有玫瑰在旁边的院子。

有人能帮我指出正确的方向吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-17 21:06:34

您可以将所有内容合并到一个查询中,如下所示:

代码语言:javascript
复制
Plant.joins(:name, :location).where(names: { common_name: "rose" }, locations: { bed_name: "side" })

这会导致一个SQL查询,如下所示:

代码语言:javascript
复制
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预取连接中的关联数据来加快速度:

代码语言:javascript
复制
Plant.includes(:name, :location).where(names: { common_name: "rose" }, locations: { bed_name: "side" })

这将同时从nameslocations加载相关记录。includes可以方便地消除(或至少减少) N+1查询。它还足够聪明,可以知道何时可以检索单个查询中的所有数据,并在更有意义的时候返回到多个查询;您不必考虑它(尽管有时它会降低效率,因此,如果您认为日志会降低性能,请注意日志)。

在这种情况下,使用includes非常有效,从而产生一个包含关联数据的单个SQL查询:

代码语言:javascript
复制
 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'
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40664644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档