使用AR在Postgres和SQLite3中使用nil值订购日期时更正不同的行为

时间:2013-12-27 01:33:13

标签: ruby-on-rails sqlite postgresql activerecord ruby-on-rails-4

我在Rails 4上并且在begin_date:date模型上拥有Project属性。我使用ActiveRecord,当nil值为User.first.projects.order(begin_date: :desc, end_date: :desc) 时,以下请求会在Postgres与SQLite上返回不同的结果:

nil

在Postgres nil中,值被视为高于现有值(因此首先出现),而在SQLite中,nil值的值最后。

  1. 我做错了什么或这是预期的行为?

  2. 我如何重构上述查询,以便在Postgres和SQLite上呈现相同的结果(关于{{1}}值)?

  3. PS。如果您有强烈的意见,我应该在所有环境中使用相同的数据库技术:我感谢您的考虑,但我知道这一点,这个问题不是关于该主题。

1 个答案:

答案 0 :(得分:3)

由于数据库的默认行为不同,因此您需要明确指定NULL的处理。

有几种方法可以执行此操作,但最便携似乎在ORDER BY DATE showing NULLS first then most recent datesSQL how to make null values come last when sorting ascending中进行了描述,它使用CASE语句显式处理空值的处理

在你的情况下,它会像:

order('case when begin_date is null then 1 else 0 end,
     begin_date desc, case when end_date is null then 1 else 0 end, end_date desc')

取决于您想要排序的位置。如果你想首先对空值进行排序,你可以交换1和0。

另一种方法是使用将null转换为非null的表达式进行排序。我不确定这方面的SQL标准在ISNULLNVLIFNULLCOALESCE方面是什么,或者甚至哪个都是sqllite和postgres的。

This recent thread讨论了Rails中缺少(和需要)一种机制来通过order来支持这一点。