Auch wenn es jetzt 2017 ist, gibt es noch keinen Konsens darüber, ob NULL
s Vorrang haben sollte. Ohne dass Sie dies explizit angeben, variieren Ihre Ergebnisse je nach DBMS.
Der Standard legt nicht fest, wie NULL-Werte im Vergleich zu Nicht-NULL-Werten geordnet werden sollen, außer dass zwei beliebige NULL-Werte als gleich geordnet betrachtet werden sollen und dass NULL-Werte entweder über oder unter allen Nicht-NULL-Werten sortiert werden sollen.
Quelle, Vergleich der meisten DBMS
Um das Problem zu veranschaulichen, habe ich eine Liste der beliebtesten Fälle für die Rails-Entwicklung zusammengestellt:
PostgreSQL
NULL
s haben den höchsten Wert.
Standardmäßig werden Nullwerte so sortiert, als wären sie größer als alle Nicht-Nullwerte.
Quelle: PostgreSQL-Dokumentation
MySQL
NULL
s haben den niedrigsten Wert.
Wenn Sie ORDER BY ausführen, werden NULL-Werte zuerst angezeigt, wenn Sie ORDER BY ... ASC ausführen, und zuletzt, wenn Sie ORDER BY ... DESC ausführen.
Quelle: MySQL-Dokumentation
SQLite
NULL
s haben den niedrigsten Wert.
Eine Zeile mit einem NULL-Wert ist höher als Zeilen mit regulären Werten in aufsteigender Reihenfolge und wird in absteigender Reihenfolge umgekehrt.
Quelle
Lösung
Leider bietet Rails selbst noch keine Lösung dafür.
PostgreSQL-spezifisch
Für PostgreSQL können Sie ganz intuitiv Folgendes verwenden:
Photo.order('collection_id DESC NULLS LAST') # NULLs come last
MySQL-spezifisch
Für MySQL könnten Sie das Minuszeichen in den Vordergrund stellen, diese Funktion scheint jedoch nicht dokumentiert zu sein. Scheint nicht nur mit numerischen Werten zu arbeiten, sondern auch mit Datumsangaben.
Photo.order('-collection_id DESC') # NULLs come last
PostgreSQL- und MySQL-spezifisch
Um beide abzudecken, scheint dies zu funktionieren:
Photo.order('collection_id IS NULL, collection_id DESC') # NULLs come last
Dieser funktioniert jedoch nicht in SQLite.
Universelle Lösung
Um Cross-Support für alle DBMS bereitzustellen, müssen Sie eine Abfrage schreiben CASE
, die bereits von @PhilIT vorgeschlagen wurde:
Photo.order('CASE WHEN collection_id IS NULL THEN 1 ELSE 0 END, collection_id')
Dies bedeutet, dass jeder Datensatz zuerst nach CASE
Ergebnissen sortiert wird (standardmäßig in aufsteigender Reihenfolge, dh die NULL
Werte sind die letzten), dann nach calculation_id
.