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.
JonB
sumber
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

Jarred
sumber
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;
d -_- b
sumber
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

DrewM
sumber
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
sumeet
sumber
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
Langdon
sumber
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
Rachit Patel
sumber
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.)

Seth
sumber
3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
YasirPoongadan
sumber
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
Danny Beckett
sumber
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

Nishu Garg
sumber
1

Ini berfungsi dengan baik:

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

position
1 
2
3
0
0
voxl.de
sumber
-8

Mengapa Anda tidak memesan dengan NULLS LAST?

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 
RedRover
sumber
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