尽管现在是 2017 年,但对于 NULLs 是否应该优先考虑,还没有达成共识。如果您没有明确说明,您的结果将因 DBMS 而异。
该标准没有指定 NULL 与非 NULL 值相比应如何排序,但任何两个 NULL 都应被视为同等排序,并且 NULL 应在所有非 NULL 值的上方或下方排序。
source, comparison of most DBMSs
为了说明问题,我整理了几个 Rails 开发中最流行的案例:
PostgreSQL
NULLs 的值最高。
默认情况下,空值排序为大于任何非空值。
source: PostgreSQL documentation
MySQL
NULLs 的值最低。
在执行 ORDER BY 时,如果执行 ORDER BY ... ASC,则首先显示 NULL 值,如果执行 ORDER BY ... DESC,则最后显示 NULL 值。
source: MySQL documentation
SQLite
NULLs 的值最低。
NULL值的行升序高于常规值的行,降序倒序。
source
解决方案
不幸的是,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 提供交叉支持,您必须使用 @PhilIT 建议的 CASE 编写查询:
Photo.order('CASE WHEN collection_id IS NULL THEN 1 ELSE 0 END, collection_id')
这意味着首先按CASE结果对每条记录进行排序(默认升序,这意味着NULL的值将是最后一个),其次是calculation_id。