MySQL Orderby một số, Nulls cuối cùng


279

Hiện tại tôi đang thực hiện một OrderBy rất cơ bản trong tuyên bố của mình.

SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC

Vấn đề với điều này là các mục nhập NULL cho 'vị trí' được coi là 0. Do đó, tất cả các mục có vị trí là NULL xuất hiện trước các mục có 1,2,3,4. ví dụ:

NULL, NULL, NULL, 1, 2, 3, 4

Có cách nào để đạt được thứ tự sau:

1, 2, 3, 4, NULL, NULL, NULL.

8
Bạn nên xem xét lại câu trả lời của người dùng1052645. Nó đơn giản hơn, không đòi hỏi kiến ​​thức về các giá trị tối đa và có thể nhanh hơn (giả sử việc đánh giá một biểu thức có thể nhanh hơn một lệnh gọi hàm).
Steve Clay

Câu trả lời:


566

MySQL có một cú pháp không có giấy tờ để sắp xếp null cuối cùng. Đặt dấu trừ (-) trước tên cột và chuyển ASC sang DESC:

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC

Về cơ bản, nó là nghịch đảo của position DESCviệc đặt các giá trị NULL cuối cùng nhưng mặt khác giống như position ASC.

Một tài liệu tham khảo tốt ở đây http://troels.arvin.dk/db/rdbms#select-order_by


79
Nó không có giấy tờ, - col_namelà một biểu thức ( 0 - col_name), mà mệnh đề ORDER BY chấp nhận. Tất nhiên điều này chỉ hoạt động cho các cột số.
Steve Clay

7
Đẹp một. Hoạt động cho datetimecột quá! (MySQL 5.5). Tôi đoán (tôi lười kiểm tra) nó hoạt động cho tất cả các cột giống như số (dấu thời gian, dấu phẩy ...).
Martin

6
@koral: đó là một biểu thức toán học đơn giản (và hữu ích) đảo ngược thứ tự, nó sẽ không bị xóa trừ khi ngôn ngữ tự thay đổi đáng kể.
Chuông

11
Như các ý kiến ​​đề xuất, nó hoạt động cho các cột số, ngày và thời gian? Nhưng, còn varchar thì sao? Nó có thể được áp dụng cho varchar là tốt? Tôi đã thử áp dụng nó cho các trường varchar, nhưng thứ tự dường như khác với việc sử dụng ASC hoặc DESC.
Sumit Desai

9
Điều này có ngăn cản việc sử dụng một chỉ mục có thể theo thứ tự theo cột không?
Tarsis

305

Tôi thấy đây là một giải pháp tốt cho hầu hết các phần:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;

6
Không xác định lại thứ tự theo công việc: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan

5
Đây là một giải pháp tốt hơn.
Rok Kralj

4
Giải pháp được chấp nhận không hoạt động với TIMESTAMP trong postgresql 9.3. Giải pháp này hiện ...
kalu

2
Khó chịu, MySQL sẽ không sử dụng một chỉ mục trên trường khi bạn thêm isnull (trường) vào thứ tự theo mệnh đề (khi sử dụng giới hạn).
Barry Kelly

3
@kalu: Trong PostgreSQL , các giá trị NULL được sắp xếp cuối cùng theo thứ tự tăng dần (và đầu tiên theo thứ tự giảm dần). Và bạn muốn sử dụng mệnh đề SQL tiêu chuẩnNULLS LAST | NULLS FIRSTđể lật nó thay vì cách giải quyết ở đây.
Erwin Brandstetter

23

Cái gì đó như

SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC

Thay thế 999999999 bằng giá trị tối đa của trường


3
Giải pháp này rất mong manh và có thể dẫn đến các lỗi không liên tục
Dmitry Bogdanovich

20

CUỐI

SELECT * FROM table_name ORDER BY id IS NULL, id ASC

4

Bạn có thể trao đổi các thể hiện của NULL với một giá trị khác để sắp xếp chúng trước (như 0 hoặc -1) hoặc cuối cùng (một số lượng lớn hoặc một chữ cái) ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC

Điều này sẽ không giải quyết được vấn đề vì chỉ mục được tham chiếu trong ORDER BY sẽ không bị ảnh hưởng bằng cách thay thế các giá trị trong câu lệnh SELECT và do đó sẽ không sửa thứ tự. Ngoài ra, hãy kiểm tra hàm COALESCE, có chức năng tương đương với việc bạn sử dụng hàm IF.
xác định

Nếu bạn đặt bí danh cho câu lệnh IF đúng, các hàng được sắp xếp như bạn mong đợi. Tôi đã sửa ví dụ của tôi.
Langdon

4

Hãy thử sử dụng truy vấn này:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC

Không cần trường hợp. IS NULL trả về 1 khi biểu thức là NULL. Xem câu trả lời của Reverbnation.
contactmatt

3

Bạn có thể kết hợp NULL của bạn trong ORDER BYtuyên bố:

select * from tablename
where <conditions>
order by
    coalesce(position, 0) ASC, 
    id DESC

Nếu bạn muốn các NULL sắp xếp ở phía dưới, hãy thử coalesce(position, 100000). (Làm cho số thứ hai lớn hơn tất cả các số khác positiontrong db.)


3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC

6
Tại sao OP nên thử điều này ? Những câu trả lời hay sẽ luôn có lời giải thích về những gì đã được thực hiện và tại sao nó được thực hiện theo cách đó, không chỉ cho OP mà cả những khách truy cập tương lai của SO có thể tìm thấy câu hỏi này và đang đọc câu trả lời của bạn.
RiggsFolly

2

Đối với một DATEcột bạn có thể sử dụng:


NULLS cuối cùng:

ORDER BY IFNULL(`myDate`, '9999-12-31') ASC

Khoảng trống cuối cùng:

ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC

1

Để đạt được kết quả sau:

1, 2, 3, 4, NULL, NULL, NULL.

Cú pháp USE, đặt -(minus sign)trước tên trường và sử dụng nghịch đảo order_type (Giống như: Nếu bạn muốn đặt hàng theo thứ tự ASC thì hãy sử dụng DESC hoặc nếu bạn muốn đặt hàng DESC thì hãy sử dụng ASC)

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC


1

Điều này đang hoạt động tốt:

SELECT * FROM tablename ORDER BY position = 0, position ASC;

position
1 
2
3
0
0

-8

Tại sao bạn không đặt hàng bởi NULLS LAST?

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 

NULLS LAST- phiên bản nào của MySQL đã được giới thiệu?
crmpicco

2
@Panique, Ý bạn là (MS) Máy chủ SQL?
d -_- b

1
câu trả lời này không áp dụng cho MySQL
PeppyHeppy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.