Sim*_*mon 5 postgresql ruby-on-rails
我正在开发一个应用程序,其中User
有许多项目,并且Project
有很多角色.Role
有一个布尔filled
属性来指示某人何时接受了该角色.
我想构建一个查询,它返回所有没有角色或具有已经填充的角色的项目.这是我到目前为止最接近的:
@user.projects.includes(:roles).where("roles.id IS NULL OR roles.filled IS TRUE").references(:roles)
Run Code Online (Sandbox Code Playgroud)
问题是roles.filled IS TRUE
查询的一部分是匹配具有填充和未填充角色的项目.我需要这个只匹配所有角色都填充的项目.
搜索PostgreSQL文档,它看起来bool_and
可能是要走的路,但我的SQL技能不是很好,我还没有设法让它工作.
我意识到我可以轻松地使用select
或者这样做reject
但我想通过查询数据库来保持它的效率.
有人可以提供一些建议吗?
更新:(简化)模型及其关系:
应用程序/模型/ user.rb
class User < ActiveRecord::Base
has_many :projects
end
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/ project.rb
class Project < ActiveRecord::Base
belongs_to :user
has_many :roles
end
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/ role.rb
class Role < ActiveRecord::Base
belongs_to :project
# `filled` is a boolean attribute with a default value of false
end
Run Code Online (Sandbox Code Playgroud)
您必须求助于聚合函数,因为条件适用于许多记录的组合( 的所有字段都roles.filled
必须为 true)。因此,您将所有角色分组projects.id
并检查是否every(roles.filled)
为真:
这是一个建议:
@user.projects.
joins("left outer join roles on roles.project_id = projects.id").
group("projects.id").
having("every(roles.filled IS TRUE) OR every(roles.id IS NULL)")
select("projects.*")
Run Code Online (Sandbox Code Playgroud)
更新:好的,这是这个 SQL 背后的逻辑:
对于每个项目,我都会检查它是否没有 Roles.id 或只有 Roles.filled。不能使用 where 子句的原因
roles.id IS TRUE
是,它只会在子句中进行分组和筛选之前选择这些行having
,从而排除这些roles.filled
行。换句话说,这相当于做roles.id is NULL AND Roles.filled IS TRUE
归档时间: |
|
查看次数: |
119 次 |
最近记录: |