【发布时间】:2021-11-14 11:42:33
【问题描述】:
我正在使用以下模型构建 Rails 应用程序:
# vote.rb
class Vote < ApplicationRecord
belongs_to :person
belongs_to :show
scope :fulfilled, -> { where(fulfilled: true) }
scope :unfulfilled, -> { where(fulfilled: false) }
end
# person.rb
class Person < ApplicationRecord
has_many :votes, dependent: :destroy
def self.order_by_votes(show = nil)
count = 'nullif(votes.fulfilled, true)'
count = "case when votes.show_id = #{show.id} AND NOT votes.fulfilled then 1 else null end" if show
people = left_joins(:votes).group(:id).uniq!(:group)
people = people.select("people.*, COUNT(#{count}) AS people.vote_count")
people.order('people.vote_count DESC')
end
end
order_by_votes 背后的想法是对 People 按未完成的选票数量进行排序,要么计算所有选票,要么只计算与给定 Show 相关联的选票。
当我对 SQLite 进行测试时,这似乎工作正常。但是当我切换到 Postgres 时,我得到了这个错误:
Error:
PeopleControllerIndexTest#test_should_get_previously_on_show:
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column people.vote_count does not exist
LINE 1: ...s"."show_id" = $1 GROUP BY "people"."id" ORDER BY people.vot...
^
如果我使用@people.to_sql 转储 SQL,这就是我得到的:
SELECT people.*, COUNT(nullif(votes.fulfilled, true)) AS people.vote_count FROM "people" LEFT OUTER JOIN "votes" ON "votes"."person_id" = "people"."id" GROUP BY "people"."id" ORDER BY people.vote_count DESC
为什么这在 Postgres 上失败但在 SQLite 上工作?我应该怎么做才能让它在 Postgres 上运行?
(PS:我用一个点命名了字段people.vote_count,所以我可以在我的视图中访问它,而无需执行另一个 SQL 查询来实际查看视图中每个人的投票数(不确定这是否有效),但即使我将字段命名为 vote_count,也会出现同样的错误。)
(PS2:我最近添加了.uniq!(:group),因为 Rails 6.2 有一些弃用警告,但我找不到任何文档,所以我不确定我做对了,没有那个错误仍然存在部分。)
【问题讨论】:
-
列不存在可能是迁移未运行的症状(或者您在运行后编辑迁移以添加列的情况)。您在数据库引擎之间切换的事实很可能只是混淆了一些东西。如果您确实编辑了迁移,请运行 db:rollback,然后再次运行 db:migrate。
-
不,没有迁移。该列在数据库中不存在,它是在 SQL 语句中创建的:
SELECT ... AS people.vote_count。 SQLite 接受这一点,但 Postgres 不接受。 :// -
哦,抱歉,我没有仔细阅读。就像下面提到的 Mu 一样,Postgres 中的别名必须只是一个列名,但它没有帮助的原因是因为 Pagy 在计算集合大小时是您的所有 SELECT 子句的blowing away。这会破坏别名,因此 Postgres 会感到困惑。作为一个快速修复,我会尝试
people.order("COUNT(#{count}) DESC")以避免使用别名。 -
是的,我已将其固定为在末尾附加
count(:all)。如果我尝试更详细的计数(只计算未完成的选票,或者只计算给定节目的选票),那么我会得到ActiveRecord::UnknownAttributeReference。不幸的是,我不得不将雄心缩小到只做left_joins(:votes).group(:id).uniq!(:group).order('COUNT(votes.id)')。也许以后我可以找到如何对不同类型的选票进行正确的排序。 :// -
罗伯特,佩吉并没有“吹嘘”任何事情。它在您传递给它的任何范围内调用
count(:all)。获取集合计数的非常标准的方法。但是,如果在你数数的时候瞄准镜爆炸了,那么……肯定是瞄准镜有问题……而且这与佩吉无关。
标签: sql ruby-on-rails ruby postgresql pagy