sql - 如何在 Rails 4 中构建跨多个表的高效选择命令?

标签 sql ruby-on-rails postgresql ruby-on-rails-4

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

structure

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

model

  • 植物 - 所属名称、所属位置
  • 名称 - has_many 植物
  • 位置 - has_many 植物

我的目标是输出侧院中每朵玫瑰的列表,并显示颜色,但我被困在选择命令上。如果我得到所有植物( p = Plant.all ),我知道我可以使用类似 <%= "#{p.name.common_name} in bed #{p.location.bed_name} has a color of #{p.color}" %> 的语句轻松创建输出。 如果我进行两次连接,我会查找更多所需的记录以及更长的搜索时间。举个例子 - 我在 16 个不同的花坛里种了 67 朵玫瑰,但是,我在侧院里只有 3 朵玫瑰。

我的直觉告诉我,我应该能够做类似的事情: 选择所有名为“玫瑰”的植物,然后从该选择中选择侧院中的所有玫瑰。

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

最佳答案

您可以将它们全部合并到一个查询中,如下所示:

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 documentation 中找到.

编辑

根据 @Dan 的评论,您可以通过使用 includes 预取联接中的关联数据来加快速度:

Plant.includes(:name, :location).where(names: { common_name: "rose" }, locations: { bed_name: "side" })

这将同时从nameslocations加载相关记录。 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'

关于sql - 如何在 Rails 4 中构建跨多个表的高效选择命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40664644/

相关文章:

mysql - 我怎样才能用 MySQL 做到这一点?

css - 使用 simple_form_for 给表单一个 CSS 类

ruby-on-rails - Rails/ActiveRecord - 查找 N 个随机项目

ruby-on-rails - scrypt 2.0.2 构建失败

sql - 如何正确索引多对多关联表?

postgresql - 如何在 Kibana 中可视化来自 Postgresql 的数据?

sql - 截断期间取消查询

sql - 基于另一列数据的列中的 SUM() 数据

mysql - 使用另一个表中的行数更新表中的字段

java - 在java中检索列表中的行值(来自Postgresql)