Mặc dù bây giờ là năm 2017, vẫn chưa có sự thống nhất về việc liệu NULL
s có nên được ưu tiên hay không. Nếu bạn không rõ ràng về nó, kết quả của bạn sẽ thay đổi tùy thuộc vào DBMS.
Tiêu chuẩn không chỉ định cách NULL nên được sắp xếp so với các giá trị không phải NULL, ngoại trừ hai NULL bất kỳ được coi là có thứ tự như nhau và NULL phải sắp xếp trên hoặc dưới tất cả các giá trị không phải NULL.
nguồn, so sánh hầu hết các DBMS
Để minh họa vấn đề, tôi đã biên soạn danh sách một vài trường hợp phổ biến nhất khi nói đến phát triển Rails:
PostgreSQL
NULL
s có giá trị cao nhất.
Theo mặc định, các giá trị null sắp xếp như thể lớn hơn bất kỳ giá trị nào không phải null.
nguồn: Tài liệu PostgreSQL
MySQL
NULL
s có giá trị thấp nhất.
Khi thực hiện ORDER BY, giá trị NULL được hiển thị đầu tiên nếu bạn thực hiện ORDER BY ... ASC và cuối cùng nếu bạn thực hiện ORDER BY ... DESC.
nguồn: Tài liệu MySQL
SQLite
NULL
s có giá trị thấp nhất.
Hàng có giá trị NULL cao hơn hàng có giá trị thông thường theo thứ tự tăng dần và nó được đảo ngược theo thứ tự giảm dần.
nguồn
Giải pháp
Thật không may, bản thân Rails vẫn chưa cung cấp giải pháp cho nó.
PostgreSQL cụ thể
Đối với PostgreSQL, bạn có thể sử dụng khá trực quan:
Photo.order('collection_id DESC NULLS LAST') # NULLs come last
MySQL cụ thể
Đối với MySQL, bạn có thể đặt trước dấu trừ, nhưng tính năng này dường như không có giấy tờ. Có vẻ như không chỉ hoạt động với các giá trị số mà còn với cả ngày tháng.
Photo.order('-collection_id DESC') # NULLs come last
PostgreSQL và MySQL cụ thể
Để bao gồm cả hai, điều này dường như hoạt động:
Photo.order('collection_id IS NULL, collection_id DESC') # NULLs come last
Tuy nhiên, cái này không hoạt động trong SQLite.
Giải pháp phổ quát
Để cung cấp hỗ trợ chéo cho tất cả DBMS, bạn phải viết truy vấn bằng cách sử dụng CASE
@PhilIT đã đề xuất:
Photo.order('CASE WHEN collection_id IS NULL THEN 1 ELSE 0 END, collection_id')
nghĩa là sắp xếp từng bản ghi trước tiên theo CASE
kết quả (theo thứ tự tăng dần mặc định, có nghĩa là NULL
các giá trị sẽ là những thứ cuối cùng), thứ hai là calculation_id
.