ruby-on-rails - Active Record 通过关系查询来查找其关系都不具有值的记录

标签 ruby-on-rails postgresql activerecord rails-activerecord ruby-on-rails-6

Rails 6.0 与 Postrgres

我有一个关系模型,其中员工 has_many 工作,并且每个工作都有一个 active 的 bool 值。

如果员工拥有的每项工作都active: false,则该员工不再受雇。因此,我想查询员工的每项工作都有 active: false 来找出哪些员工不再受雇。

我尝试过类似的事情

class Employee < ApplicationRecord
  scope :terminated, -> { 
    includes(:jobs).
      where.not(jobs: {
        active: true,
      })
  }

但这指的是查找从事任何工作但activetrue的员工。我想找到每个工作都活跃false的员工。 AR 本身可以做到这一点吗?

最佳答案

一种方法是连接作业表两次并使用别名:

SELECT "employees".* FROM "employees" 
INNER JOIN "jobs" 
  ON "jobs"."employee_id" = "employees"."id" 
INNER JOIN "jobs" "inactive_jobs" 
  ON "inactive_jobs"."employee_id" = "employees"."id" 
  AND "inactive_jobs"."active" = 0 
GROUP BY "employees"."id" 
HAVING COUNT("jobs"."id") = COUNT("inactive_jobs"."id") LIMIT ?

ActiveRecord 并没有真正直接的方法来进行别名连接,但通过一些 Arel 技巧你可以实现它。

class Employee < ApplicationRecord
  has_many :jobs
  
  def self.terminated
    jobs = Job.arel_table
    # Needed to generate a join with an alias
    inactive_jobs = Job.arel_table.alias('inactive_jobs')
    # joins all the jobs
    joins(
      :jobs
    )
    # joins jobs where active: false
    .joins(
      self.arel_table.join(
          inactive_jobs,
          Arel::Nodes::InnerJoin
        ).on(
          inactive_jobs[:employee_id].eq(self.arel_table[:id])
            .and(inactive_jobs[:active].eq(false))
        ).join_sources
    )
    # groups on employee id
    .group(:id)
    # Set a condition on the group that the jobs must equal the number of inactive jobs
    .having(jobs[:id].count.eq(inactive_jobs[:id].count))
  end
end

如果您添加计数器缓存,您可以作弊并删除第二个连接:

class Job
  belongs_to :employee, counter_cache: true
end

class Employee < ApplicationRecord
  has_many :jobs

  def self.terminated
    joins(:jobs)
      .where(jobs: { active: false })
      .group(:id)
      .having(arel_table[:jobs_count].eq(Job.arel_table[Arel.star].count)) 
  end
end

在这里,您将缓存的值与连接行数进行比较。

关于ruby-on-rails - Active Record 通过关系查询来查找其关系都不具有值的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67082610/

相关文章:

ruby-on-rails - 如何在 Rails 查询中缓存数据库产生的列表

ruby-on-rails - 如何遍历匹配正则表达式的数组元素?

postgresql - Postgres 错误 : Division by zero on bulk update SQL

sql - Postgres无限 self 加入

ruby-on-rails - 在 ActiveRecord 关联范围 block 内访问所有者

ruby-on-rails - Sequel 与 ActiveRecord 结合使用有什么问题吗?

ruby-on-rails - 部署到 Heroku 的问题

ruby-on-rails - 如何计算数组中连续的数字?

string - 向现有字符串添加一个字符

php - CakePHP 从 habtm 返回多条记录