虽然现在已经是2017年了,但是关于NULL
应该如何优先处理仍然没有共识。如果您不明确说明,那么您的结果将因DBMS而异。
标准并未指定如何比较NULL和非NULL值的顺序,除了任何两个NULL都被认为是等有序的,并且NULL应该在所有非NULL值之上或之下排序。
来源,大多数DBMS的比较
为了说明问题,我列出了一些最流行的Rails开发案例:
PostgreSQL
NULL
具有最高的值。
默认情况下,null值排序时会被认为比任何非null值都要大。
来源:PostgreSQL文档
MySQL
NULL
具有最低的值。
在进行ORDER BY时,如果使用ORDER BY ... ASC,则NULL值将首先呈现;如果使用ORDER BY ... DESC,则它们将最后呈现。
来源:MySQL文档
SQLite
NULL
具有最低的值。
当按升序排列时,具有NULL值的行高于具有常规值的行,并且在按降序排序时相反。
来源
解决方案
不幸的是,Rails本身还没有提供解决方案。
PostgreSQL特定
对于PostgreSQL,您可以直观地使用:
Photo.order('collection_id DESC NULLS LAST')# NULLs come last
MySQL特定
对于MySQL,您可以将减号放在前面,但似乎此功能未经记录。 它不仅适用于数字值,还适用于日期。
Photo.order('-collection_id DESC') # NULLs come last
PostgreSQL和MySQL特定内容
为了涵盖两种数据库,这个看起来是可以的:
Photo.order('collection_id IS NULL, collection_id DESC') # NULLs come last
但是,在SQLite中,这个无法工作。
通用解决方案
为了提供所有DBMS的交叉支持,您需要编写一个使用CASE
的查询,@PhilIT已经建议过了:
Photo.order('CASE WHEN collection_id IS NULL THEN 1 ELSE 0 END, collection_id')
它首先按照每条记录的CASE
结果排序(默认升序,这意味着NULL
值将是最后一个),然后再按照calculation_id
排序。
p = Photo.arel_table; Photo.order(p[:collection_id].eq(nil)).order(p[:collection_id].desc)
- m_xNULLS LAST
不能让您将.last()
链接到查询中。 我在下面发布了一个解决方法。 - Lanny BoseIS NULL
排序会把NULL行放在最后?你可能认为它会把它们放在最前面。 - jackocnr