【问题标题】:Rails order active record results based on one column and another if nullRails 根据一列对活动记录结果进行排序,如果为空则为另一列
【发布时间】:2023-03-19 09:52:02
【问题描述】:

所以我有一个返回一些记录的活动记录查询,假设它看起来像这样。

jobs = Job.where(:user_id => current_user.id)

如您所料,这将返回 current_user 的作业。假设作业有两个日期,deadline_datedue_date。如果我想在deadline_date 上订购,我可以这样做......

jobs.order("deadline_date asc")

按预期工作,现在图像我在工作模型中有这样的东西。

class Job < ActiveRecord::Base
 def deadline_date
  self.read_attribute(:deadline_date) || self.due_date
 end
end

因此,如果它不为零,则作业将显示其deadline_date,否则它将回退使用due_date。因此,为了对此进行排序,我执行了以下操作...

jobs.sort_by{|job| job.deadline_date}
jobs.sort_by{|job| job.deadline_date}.reverse

这解决了我的问题,但我想知道是否有更好的选择,是否可以使用 SQL 来实现?这也会产生一些重复的代码,因为我的控制器中有一个 sort_order 变量,我可以像这样直接传递......

jobs.order(sort_order)

现在看起来更像这样...

if params[:sort] == "deadline_date"
 if params[:order] == "asc"
  jobs.sort_by{|job| job.deadline_date}
 else
  jobs.sort_by{|job| job.deadline_date}.reverse
 end
else
 jobs.order(sort_order)
end

注意:这是一个随意的例子,实际上它有点混乱,但你明白了。所以我正在寻找一种 SQL 替代方案或关于如何改进它的建议。干杯

【问题讨论】:

  • 如果没有错,基本上你想检查可排序列是否不为空,然后按该列排序,否则按另一列排序???
  • 是的,我希望排序基于deadline_date,但如果该字段为空,则使用due_date。 COALESCE 函数可以解决问题。

标签: sql ruby-on-rails ruby activerecord


【解决方案1】:

如果我理解正确,您应该可以使用COALESCE SQL 函数来执行此操作:

jobs.order(Arel.sql("COALESCE(deadline_date, due_date)"))

这与 Ruby 中的 deadline_date || due_date 几乎相同。

我相信它是一个标准的 SQL 东西,所以它应该适用于大多数 SQL 方言。

【讨论】:

  • 请注意:从 Rails 6+ 开始,这会导致错误。在那里,应该是:jobs.order(Arel.sql("COALESCE(deadline_date, due_date)"))
  • 确实,我已经更新了我原来的答案,干杯 macav。
猜你喜欢
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
  • 1970-01-01
相关资源
最近更新 更多