查找计数大于零的所有记录

时间:2013-11-25 02:01:19

标签: sql ruby-on-rails ruby-on-rails-3 activerecord

我正在尝试做一些我认为很简单的事情,但似乎不是。

我有一个有很多职位空缺的项目模型。

class Project < ActiveRecord::Base

  has_many :vacancies, :dependent => :destroy

end

我希望获得至少有1个空缺的所有项目。 我试过这样的事情:

Project.joins(:vacancies).where('count(vacancies) > 0')

但它说

SQLite3::SQLException: no such column: vacancies: SELECT "projects".* FROM "projects" INNER JOIN "vacancies" ON "vacancies"."project_id" = "projects"."id" WHERE ("projects"."deleted_at" IS NULL) AND (count(vacancies) > 0)

10 个答案:

答案 0 :(得分:135)

1)获得至少有1个空缺的项目:

Project.joins(:vacancies).group('projects.id')

2)获得超过1个空缺的项目:

Project.joins(:vacancies).group('projects.id').having('count(project_id) > 1')

3)或者,如果Vacancy模型设置了计数器缓存:

belongs_to :project, counter_cache: true

然后这也会起作用:

Project.where('vacancies_count > ?', 1)

vacancy的变形规则可能需要specified manually

答案 1 :(得分:49)

joins默认情况下使用内部联接,因此使用Project.joins(:vacancies)实际上只会返回具有关联空缺的项目。

更新:

正如@mackskatz在评论中所指出的,如果没有group子句,上面的代码将返回具有多个空缺的项目的重复项目。要删除重复项,请使用

Project.joins(:vacancies).group('projects.id')

答案 2 :(得分:27)

是的,vacancies不是联接中的字段。我相信你想要:

Project.joins(:vacancies).group("projects.id").having("count(vacancies.id)>0")

答案 3 :(得分:11)

# None
Project.joins(:vacancies).group('projects.id').having('count(vacancies) = 0')
# Any
Project.joins(:vacancies).group('projects.id').having('count(vacancies) > 0')
# One
Project.joins(:vacancies).group('projects.id').having('count(vacancies) = 1')
# More than 1
Project.joins(:vacancies).group('projects.id').having('count(vacancies) > 1')

答案 4 :(得分:3)

在Rails 4+中,您还可以使用 includes eager_load 获得相同的答案:

Vector3 groupCenter = parentObject.getComponent<Renderer>().bounds.center;

答案 5 :(得分:1)

将has_many表的内部联接与groupuniq结合使用可能会非常低效,在SQL中,将其更好地实现为使用EXISTS的半联接与相关的子查询。

这允许查询优化器探测空位表,以检查是否存在具有正确project_id的行。不管是一行还是一百万个都有那个project_id。

在Rails中并不是那么简单,但是可以通过以下方式实现:

Project.where(Vacancies.where("vacancies.project_id = projects.id").exists)

类似地,找到所有没有空缺的项目:

Project.where.not(Vacancies.where("vacancies.project_id = projects.id").exists)

答案 6 :(得分:0)

没有太多的Rails魔法,你可以这样做:

Project.where('(SELECT COUNT(*) FROM vacancies WHERE vacancies.project_id = projects.id) > 0')

这种类型的条件适用于所有Rails版本,因为大部分工作都是直接在DB端完成的。另外,链接.count方法也可以很好地工作。我以前曾被Project.joins(:vacancies)等问题烧伤过。当然,它有利有弊,因为它不是DB不可知的。

答案 7 :(得分:0)

我认为有一个更简单的解决方案:

Project.joins(:vacancies).uniq

答案 8 :(得分:0)

您还可以将EXISTSSELECT 1一起使用,而不是从vacancies表中选择所有列:

Project.where("EXISTS(SELECT 1 from vacancies where projects.id = vacancies.project_id)")

答案 9 :(得分:-5)

错误告诉你,空缺不是项目中的一个列,基本上。

这应该有效

Project.joins(:vacancies).where('COUNT(vacancies.project_id) > 0')