Nomor MySQL Orderby, Nulls terakhir


280

Saat ini saya sedang melakukan OrderBy yang sangat mendasar dalam pernyataan saya.

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

Masalah dengan ini adalah bahwa entri NULL untuk 'posisi' diperlakukan sebagai 0. Oleh karena itu semua entri dengan posisi sebagai NULL muncul sebelum orang-orang dengan 1,2,3,4. misalnya:

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

Apakah ada cara untuk mencapai pemesanan berikut:

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

8
Anda harus mempertimbangkan kembali jawaban user1052645. Lebih sederhana, tidak memerlukan pengetahuan tentang nilai-nilai maks, dan bisa lebih cepat (dengan asumsi mengevaluasi ekspresi mungkin lebih cepat daripada panggilan fungsi).
Steve Clay

Jawaban:


568

MySQL memiliki sintaksis tanpa dokumen untuk mengurutkan null yang terakhir. Tempatkan tanda minus (-) di depan nama kolom dan alihkan ASC ke DESC:

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

Ini pada dasarnya kebalikan dari position DESCmenempatkan nilai NULL yang terakhir tetapi sebaliknya sama dengan position ASC.

Referensi yang baik ada di sini http://troels.arvin.dk/db/rdbms#select-order_by


79
Itu bukan dokumen, - col_nameadalah ekspresi ( 0 - col_name), yang diterima oleh klausa ORDER BY. Tentu saja ini hanya berfungsi untuk kolom angka.
Steve Clay

7
Bagus Bekerja untuk datedan timekolom juga! (MySQL 5.5). Saya kira (saya malas memeriksa) berfungsi untuk semua kolom angka-suka (timestamp, float ...).
Martin

6
@koral: ini adalah ekspresi matematika sederhana (dan berguna) yang membalik urutan, itu tidak akan dihapus kecuali bahasa itu sendiri berubah secara dramatis.
Bell

11
Seperti komentar yang disarankan, itu berfungsi untuk kolom angka, tanggal dan waktu? Tapi, bagaimana dengan varchar? Bisakah itu diterapkan untuk varchar juga? Saya mencoba menerapkannya ke bidang varchar, tetapi urutannya tampaknya berbeda dari menggunakan ASC atau DESC.
Sumit Desai

9
Bukankah ini akan mencegah penggunaan indeks yang mungkin pada kolom pesanan?
Tarsis

306

Saya menemukan ini menjadi solusi yang baik untuk sebagian besar:

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

6
Tanpa mendefinisikan ulang urutan karya: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan

5
Ini solusi yang lebih baik.
Rok Kralj

4
Solusi yang diterima tidak bekerja dengan TIMESTAMP di postgresql 9.3. Solusi ini tidak ...
kalu

2
Anehnya, MySQL tidak akan menggunakan indeks pada bidang ketika Anda menambahkan isnull (bidang) ke urutan dengan klausa (saat menggunakan batas).
Barry Kelly

3
@kalu: Di PostgreSQL , nilai NULL diurutkan terakhir dalam urutan naik (dan pertama dalam urutan menurun). Dan Anda lebih suka menggunakan klausa SQL standarNULLS LAST | NULLS FIRSTuntuk membaliknya alih-alih solusi di sini.
Erwin Brandstetter

23

Sesuatu seperti

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

Ganti 999999999 dengan apa nilai maksimal bidang tersebut


3
Solusi ini rapuh dan dapat menyebabkan bug berselang
Dmitry Bogdanovich

20

NULL TERAKHIR

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

4

Anda dapat menukar contoh NULL dengan nilai yang berbeda untuk mengurutkannya terlebih dahulu (seperti 0 atau -1) atau terakhir (sejumlah besar atau huruf) ...

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

Ini tidak akan menyelesaikan masalah karena indeks yang dirujuk dalam ORDER BY tidak akan terpengaruh dengan mengganti nilai dalam pernyataan SELECT, dan dengan demikian tidak akan memperbaiki pemesanan. Juga, periksa fungsi COALESCE, yang secara fungsional setara dengan penggunaan Anda atas fungsi IF.
mendefinisikan

Jika Anda menyebut pernyataan IF dengan benar, baris akan dipesan seperti yang Anda harapkan. Saya memperbaiki contoh saya.
Langdon

4

Coba gunakan permintaan ini:

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

Tidak perlu kasing. IS NULL mengembalikan 1 ketika ekspresi NULL. Lihat jawaban gema.
contactmatt

3

Anda dapat menyatukan NULL Anda dalam ORDER BYpernyataan:

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

Jika Anda ingin NULL mengurutkan di bagian bawah, coba coalesce(position, 100000). (Buat angka kedua lebih besar dari yang lainnya positiondi db.)


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

6
Mengapa OP harus mencoba ini ? Jawaban yang baik akan selalu memiliki penjelasan tentang apa yang dilakukan dan mengapa dilakukan seperti itu, tidak hanya untuk OP tetapi untuk pengunjung masa depan ke SO yang mungkin menemukan pertanyaan ini dan membaca jawaban Anda.
RiggsFolly

2

Untuk DATEkolom, Anda dapat menggunakan:


NULLS terakhir:

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

Kosong lalu:

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

1

Untuk mencapai hasil berikut:

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

GUNAKAN sintaks, tempatkan -(minus sign)sebelum nama bidang dan gunakan inverse order_type (Seperti: Jika Anda ingin memesan dengan pesanan ASC kemudian gunakan DESC atau jika Anda ingin pesanan DESC maka gunakan ASC)

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


1

Ini berfungsi dengan baik:

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

position
1 
2
3
0
0

-8

Mengapa Anda tidak memesan dengan NULLS LAST?

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

NULLS LAST- versi MySQL apa yang diperkenalkan?
crmpicco

2
@Panique, Maksud Anda (MS) SQL Server?
d -_- b

1
jawaban ini tidak berlaku untuk MySQL
PeppyHeppy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.