基于多个子模型条件/状态进行排序

时间:2016-10-03 12:13:22

标签: ruby-on-rails postgresql

我有一个具有多个间隔的房间模型。 Intervals具有start_date和end_date属性。我想根据以下条件订购客房

1-没有间隔的房​​间 2-房间,任何间隔,start_date> Date.today 没有任何间隔的3-房间,带有start_date> Date.tody

我想以这样的方式对房间进行排序:满足1的房间首先出现,然后使用postgresql查询而不是模型上的方法满足2然后3房间。

虽然使用下面的查询/范围找出哪些房间没有间隔没有问题

joins("LEFT OUTER JOIN intervals ON rooms.id = intervals.room_id").where("intervals.id is NULL")

我在单个查询中遇到3个条件的排序问题,我尝试了以下

Room.joins("LEFT OUTER JOIN intervals ON rooms.id = intervals.room_id").order("CASE WHEN intervals.id IS NULL THEN 1 END ASC")

此查询的问题在于,如果您在其上调用distinct,则会收到错误PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list,另一个问题即使您在此处调用distinct并且它正常工作,您只能按一个条件进行排序第1步。

我的想法是使用case条件生成一个函数,根据3个条件给出生成列的值,并给第一个值1,第二个值2和第三个值3,并按此计算值排序,每当我尝试它时,我会被上面提到的错误击中。任何帮助将不胜感激。

这是我结合所有3个条件的试验:

Room.joins("LEFT OUTER JOIN intervals ON rooms.id = intervals.room_id").group("room.id").order("CASE WHEN room.id IS NULL THEN 1 WHEN COUNT(CASE WHEN intervals.start_date > '#{Date.today.to_s(:db)}' THEN 1 END) > 0 THEN 2 WHEN COUNT(CASE WHEN intervals.start_date > '#{Date.today.to_s(:db)}' THEN 1 END) = 0 THEN 3 END")

然而,这会给出错误:PG :: GroupingError:ERROR:列“intervals.id”必须出现在GROUP BY子句中或用于聚合函数

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

在此"具体"例如,我会针对您的特定业务规则对模式进行去规范化。请记住,您可能需要在某些时候进行分页,并且需要在db进行排序。

为此,我会在模型中添加一列以指示排序优先级:

add_column :rooms, :sort_priority, :integer, null: false, default: 0

然后在我的间隔模型中,我将包含一个设置优先级

的before_save过滤器
before_save -> {
  if (start_date < blah blah blah)
    self.priority = 1
  elsif (blah blah)
    etc...
  end
}

然后我会在我的参考文献中反映这一点

class Room
  has_many :intervals, -> {order :priority, :start_date}
end