ruby-on-rails - 如何在不使用包含的情况下避免 n + 1?

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

我有两个模型

class Task < AR::Base
  habtm :user_groups
end

class UserGroup < AR::Base
  habtm :tasks
end

要求:

t = Task.where(id: 45734)
t.user_group_ids #[54, 523, 78]

上面一行会引起2次查询。

我想在不使用 includes 的情况下在一个查询中执行此操作。

我的尝试:

tasks = Task.joins(:user_groups).select('tasks.id, user_groups.id as ug_id').where(customer_id: 5)

但即使对于关联多个组的任务,它也只会检索单个用户组。

更新

正如麦克斯建议的那样:

t = Task.joins('LEFT OUTER JOIN tasks_user_groups ON tasks_user_groups . analysis_task_id  =  tasks . id  INNER JOIN  user_groups  ON  user_groups . id  =  tasks_user_groups . user_group_id').select('user_groups.id').where(id: 36299)

现在我得到两个任务,它们具有相同的 ID 但有两个不同的用户组。

请建议如何实现它。

最佳答案

.joins 使用 INNER LEFT JOIN,因此它只会提供来自在 users_groups 中匹配的任务的行。

.includes 通过使用两个单独的查询来解决这个问题。

您想要的是外连接。

# Rails 5
Task.left_outer_joins(:user_groups)

# Rails 4
tasks = Task.joins('LEFT OUTER JOIN user_groups ON user_groups.task_id = tasks.id')

参见:

What is the difference between "INNER JOIN" and "OUTER JOIN"?

关于ruby-on-rails - 如何在不使用包含的情况下避免 n + 1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43689302/

相关文章:

ruby-on-rails - 如何测试文件上传模型?

java - JPA 单表层次结构中的 PostgreSQL 标识

ruby-on-rails - Heroku 与 Rails 发生错误 : syntax error, 意外的 keywords_end,期望输入结束

ruby-on-rails - 在 Heroku 上部署 Activeadmin 时为 "uninitialized constant AdminUser"

ruby-on-rails - rails - 在保存到服务器之前将 DateTime 转换为 UTC

mysql - 有人可以帮我理解这个 MySql 语句并将其转换为 Postgresql 吗?

java - 如何使用 Java 使用用户事务显式锁定 Postgresql 表

sql - 选择 Rails 中一个属性的最大值限定为另一个属性的记录

ruby-on-rails - Ruby on Rails : How to link/route from one view/page to another view/page with a different controller

ruby-on-rails - Rails 4 中命名空间路由的单独域