【发布时间】:2021-02-19 06:48:20
【问题描述】:
我有一个复杂的数据库查询,它根据房地产列表属性、学校的绩效统计数据以及每个列表与公共交通的距离来选择学校。用户创建Search对象,search.rb中的方法find_schools有这样的查询:
School.where(id: school_ids).narrow_schools_for_search(self,prop_type,status,year).joins(listings:
:cta_listings).joins(:performance_stats).where("cta_listings.distance <= ?",
self.cta_distance).where.not(performance_stats: {"#{sort_column.to_sym}" =>
nil}).distinct.limit(30).order("performance_stats.#{sort_column} DESC")
School.rb
scope :narrow_schools_for_search, ->(search,prop_type,status,year) {joins(:listings).joins(:performance_stats)
.where("listings.beds >= ?",search.beds).where("listings.price <= ?",search.max_price)
.where("listings.price >= ?",search.min_price).where(listings: {prop_type: prop_type, status: status})
.where(performance_stats: {year: year}).distinct}
has_many :performance_stats, dependent: :destroy
has_many :assignments, dependent: :destroy
has_many :listings, through: :assignments
Listing.rb
has_many :assignments, dependent: :destroy
has_many :schools, through: :assignments
has_many :cta_listings, dependent: :destroy
has_many :cta_stations, through: :cta_listings
has_many :metra_listings, dependent: :destroy
has_many :metra_stations, through: :metra_listings
PerformanceStat.rb
belongs_to :school
我需要按关联表 PerformanceStats 中的属性排序的学校,这是用户定义的属性 sort_column。该查询在开发环境(sqlite3)中工作,但在登台应用程序(PG)上失败并出现以下错误:
ActiveRecord::StatementInvalid (PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
我需要添加一个 select 语句,其中包含我用来对学校进行排序的列名。
其他帖子like this one 的建议是:
Widget.select('"widgets".*, "widget_steps.name"')
所以,就我而言,我尝试了这个:
sort_for_select = "performance_stats.#{sort_column}"
School.select('"schools".*, "#{sort_for_select"').where(id: school_ids).narrow_schools_for_search(self,prop_type,status,year).joins(listings:
:cta_listings).joins(:performance_stats).where("cta_listings.distance <= ?",
self.cta_distance).where.not(performance_stats: {sort_column.to_sym =>
nil}).distinct.limit(30).order("performance_stats.#{sort_column} DESC")
但我的编辑表明我实际上并没有逃到 ruby。反正我试过了,果然失败了
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column "#{sort_for_select}" does not exist.
然后我尝试对sort_column 进行硬编码:
School.select('"schools".*, "performance_stats.grall_adjpicalc"').where(id: school_ids).narrow_schools_for_search(self,prop_type,status,year).joins(listings:
:cta_listings).joins(:performance_stats).where("cta_listings.distance <= ?",
self.cta_distance).where.not(performance_stats: {grall_adjpicalc:
nil}).distinct.limit(30).order("performance_stats.grall_adjpicalc DESC")
这在开发环境中有效,但如果在暂存应用程序上失败并出现此错误:
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column "performance_stats.grall_adjpicalc" does not exist
所以在这一点上,我必须每次都部署以测试新想法。我知道开发中的 PG 会是理想的,但我花了整整一周的时间试图改变并且无法让它发挥作用。最终失去了一切,不得不从头开始重新播种。
我有 3 个问题:
-
我对 Select 语句做错了什么?
-
有没有另一种快速的方法来避免这个问题?我在想而不是 Distinct,也许我可以使用 uniq,转换为数组,然后对数组进行相应的排序。
-
如何将变量
sort_column放入 select 语句中?
非常感谢任何想法或建议!
【问题讨论】:
-
字符串插值(如
"text #{variable} text")仅适用于双引号内。所以如果foo = "bar"那么"#{foo}" == "bar"但'#{foo}' != "bar" && '#{foo}' == "\#\{foo\}"。我不知道选择的修复方法是什么,因为 SQL 不是我的专长 -
然而,PG 错误
column "performance_stats.grall_adjpicalc" does not exist是不言自明的——该列不存在,可能是由于没有运行生产环境中所需的迁移。 -
grall_adjpicalc 肯定存在,它在开发环境中工作。只有在生产中,它才会因为列不存在的语句而失败。我认为 postgres 需要不同的语法,因为我加入 :performance_stats 和 :schools。
标签: postgresql select ruby-on-rails-5 arel pg-query