我在项目模型上有以下范围,以查找至少已完成 80 项众筹 promise 的项目或已经达到目标的项目:
class Project < ActiveRecord::Base
scope :popular, -> { collecting.where("80 <= (?) OR goal <= (?)",
Pledge.select('COUNT(*)').where("project_id = projects.id").where(paid: true),
Pledge.select('SUM(amount)').where("project_id = projects.id").where(paid: true))
}
(...)
end
这工作得很好,并为 Postres 生成以下 SQL:
Project.popular
# SELECT "projects".* FROM "projects" WHERE "projects"."state" = 'collecting' AND (80 <= (SELECT COUNT(*) FROM "pledges" WHERE (project_id = projects.id) AND "pledges"."paid" = 't') OR goal <= (SELECT SUM(amount) FROM "pledges" WHERE (project_id = projects.id) AND "pledges"."paid" = 't'))
获取计数也很重要:
Project.popular.count
# SELECT COUNT(*) FROM "projects" WHERE "projects"."state" = 'collecting' AND (80 <= (SELECT COUNT(*) FROM "pledges" WHERE (project_id = projects.id) AND "pledges"."paid" = 't') OR goal <= (SELECT SUM(amount) FROM "pledges" WHERE (project_id = projects.id) AND "pledges"."paid" = 't'))
好的,子选择很好,但我觉得有更好、更有效的方法来做到这一点。我已经尝试过 joins
和 sum
,但是使用聚合函数的强制性 group
会破坏 Project.popular.count
.
有什么重构方法吗?也许只是一种以哈希表示法执行 where("project_id = projects.id")
的方法?
最佳答案
我不知道这对你是否有好处,因为我无法用 ActiveRecord 行话表达下面的查询,但如果你可以,这将比当前生成的糟糕查询有很大改进
select "projects".*, project_count, project_amount
from
"projects"
inner join (
select
id,
count(*) as project_count,
sum(amount) as project_amount
from pledges
group by id
where paid
) pledges using (id)
where
"projects"."state" = 'collecting'
and
(project_count >= 80 or project_amount >= goal)
关于ruby-on-rails - 在 WHERE 中重构具有两个子选择的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24578358/