Ruby on Rails活动记录查询

时间:2015-09-18 04:07:59

标签: ruby-on-rails ruby activerecord model

雇主和工作。雇主有很多工作。乔布斯有一个布尔字段。

我正在尝试查询并查找有多个已启动作业的雇主的计数。

我该怎么做?

Employer.first.jobs.where(已启动:true).count

我是否使用带计数器的循环,或者我是否可以使用查询进行循环?

谢谢!

4 个答案:

答案 0 :(得分:1)

您可以加入条件

Employer.joins(:jobs).where(jobs: {started: true}).count

答案 1 :(得分:1)

您可以在Employer模型中创建这样的范围:

def self.with_started_job
  joins(:jobs)
    .where(jobs: { started: true })
    .having('COUNT(jobs.id) > 0')
end

然后,为了获得已经开始工作的雇主数量,您可以使用Employer.with_started_job.count

答案 2 :(得分:1)

缺少的是group by子句。使用.group()然后count。像

Employer.select("employers.id,count(*)").joins(:jobs).where("jobs.started = 1").group("employers.id")

这样的东西

查询连接两个表,消除了错误的记录,然后计算每个雇员的总记录数.id组合在一起。

答案 3 :(得分:0)

探索性编程的时间!

鉴于我不太熟悉SQL,我这样做的方式可能不是最佳的。我没有使用子查询就无法使用两个聚合。所以我将任务分成两部分:

  • 取得所有有多份工作的雇主
  • 计算结果集中的条目数

当然,所有这些都在数据库级别上!没有原始SQL,所以在这里和那里使用Arel。以下是我的想法:

class Employer < ActiveRecord::Base
  has_many :jobs

  # I explored my possibilities using this method: fetches
  # all the employers and number of jobs each has started.
  # Looks best> Employer.with_started_job_counts.map(&:attributes)
  # In the final method this one is not used, it's just handy.
  def self.with_started_job_counts
    jobs = Job.arel_table
    joins(:jobs).select(arel_table[Arel.star],
                        jobs[:id].count.as('job_count'))
      .merge(Job.where(started: true))
      .group(:id)
  end

  # Alright. Now try to apply it. Seems to work alright.
  def self.busy
    jobs = Job.arel_table

    joins(:jobs).merge(Job.where(started: true))
                .group(:id)
                .having(jobs[:id].count.gt 1)
  end

  # This is one of the tricks I've learned while fiddling
  # with Arel. Counts any relations on the database level.
  def self.generic_count(subquery)
    from(subquery).count
  end

  # So now... we get this.
  def self.busy_count
    generic_count(busy)
  end
  # ...and it seems to get what we need!
end

结果SQL很大。不是很大,但你可能不得不用它解决性能问题。

SELECT COUNT(*)
FROM (
  SELECT "employers".*
  FROM "employers"
    INNER JOIN "jobs" ON "jobs"."employer_id" = "employers"."id"
  WHERE "jobs"."started" = ?
  GROUP BY "employers"."id"
  HAVING COUNT("jobs"."id") > 1
) subquery  [["started", "t"]]

......但是,它似乎确实得到了结果。