我正在尝试做一些我认为很简单的事情,但似乎不是。
我有一个有很多职位空缺的项目模型。
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)
。
答案 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表的内部联接与group
或uniq
结合使用可能会非常低效,在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)
您还可以将EXISTS
与SELECT 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')