Ruby on rails 更正在Postgres中使用nil值排序日期和使用AR排序SQLite3时的不同行为
我在Rails 4上,在Ruby on rails 更正在Postgres中使用nil值排序日期和使用AR排序SQLite3时的不同行为,ruby-on-rails,sqlite,postgresql,activerecord,ruby-on-rails-4,Ruby On Rails,Sqlite,Postgresql,Activerecord,Ruby On Rails 4,我在Rails 4上,在项目模型上有一个开始日期:日期属性。我正在使用ActiveRecord,当存在nil值时,以下请求在Postgres和SQLite上返回不同的结果: User.first.projects.order(begin_date: :desc, end_date: :desc) 在Postgres中,nil值被视为比现有值高的值(因此排在第一位),而在SQLite记录中,nil值排在最后 我是做错了什么,还是这是预期的行为 如何重构上述查询,使其在Postgres和SQLit
项目
模型上有一个开始日期:日期
属性。我正在使用ActiveRecord,当存在nil
值时,以下请求在Postgres和SQLite上返回不同的结果:
User.first.projects.order(begin_date: :desc, end_date: :desc)
在Postgres中,nil
值被视为比现有值高的值(因此排在第一位),而在SQLite记录中,nil
值排在最后
nil
值)请注意,如果您有强烈的意见认为我应该在所有环境中使用相同的db技术:谢谢您的考虑,但我知道这一点,这个问题与该主题无关。由于默认行为在数据库中不同,您需要明确指定
NULL
的处理方式
有几种方法可以做到这一点,但最可移植的方法似乎在和中进行了描述,它使用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标准是什么,包括ISNULL
、NVL
、IFNULL
和COALESCE
,甚至不确定这两种标准对sqllite和postgres都是通用的
讨论Rails中缺乏(以及需要)一种机制来支持这一点,通过
顺序您希望null
s位于哪一端?我更希望它们的排名低于具有现有值的记录。嗯,很有趣。有点伤心。当涉及到按两列排序(即,如果第一列相等,则按第二列排序)时,您可能对我的情况有任何明确的代码建议吗?您也可以使用COALESCE(begin_date,X)
将空值转换为更可预测的值(当然,假设存在合适的X
s)是的,大家都开始在这件小事上遵循标准了。最后因此,您可以在SQLite和PostgreSQL(甚至MySQL)中合并。@muistooshort您是否愿意详细说明在上述场景中使用COALESCE
的实现是什么样子的。聚结的问题也在那里被注意到。