it-swarm.asia

Mengapa NULL diurutkan terlebih dahulu?

Mengapa ketika kita memiliki nilai NULL dalam kolom dan kita memesan berdasarkan nilai yang naik, NULL diurutkan terlebih dahulu?

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

hasil dalam

NULL
1
2
3
4

Saya terus berpikir bahwa NULL berarti "Tidak Pasti" atau mungkin "Tidak Diketahui". Jika itu benar, bukankah mereka akan mengurutkan terakhir, karena nilainya bisa lebih besar dari semua nilai lainnya? (Atau ini opsi sortir?)

Saya menggunakan SQL Server 2008R2, tetapi saya menduga ini benar di semua Server SQL, dan mungkin di semua RDBMS.

20
Richard

BOL : Nilai NULL menunjukkan bahwa nilainya tidak diketahui. Nilai NULL berbeda dari nilai kosong atau nol. Tidak ada dua nilai nol yang sama. Perbandingan antara dua nilai nol, atau antara NULL dan nilai lainnya, menghasilkan tidak diketahui karena nilai setiap NULL tidak diketahui.

NULL berarti tidak dikenal. Tidak ada interpretasi lain yang valid.

Jika itu benar, bukankah mereka akan mengurutkan terakhir, karena nilainya bisa lebih besar dari semua nilai lainnya?

Tidak ada bisa . Tidak ada nilai potensial . Tidak dikenal tidak dikenal tidak diketahui.

Mengenai mengapa ini muncul pertama kali, bukan yang terakhir, ini tidak dipenuhi oleh standar SQL yang dipublikasikan dan sayangnya diserahkan kepada kebijaksanaan vendor RDBMS:

Wikipedia : Standar SQL tidak secara eksplisit mendefinisikan urutan urutan default untuk Nulls. Sebaliknya, pada sistem yang menyesuaikan, Nulls dapat diurutkan sebelum atau setelah semua nilai data dengan menggunakan klausa NULLS FIRST atau NULLS LAST dari daftar ORDER BY, masing-masing. Namun, tidak semua vendor DBMS menerapkan fungsi ini. Vendor yang tidak menerapkan fungsi ini dapat menentukan perawatan yang berbeda untuk pengurutan Null di DBMS.

20

Anda benar bahwa NULL dapat berarti 'Tidak Menentu' atau 'Uknownn' atau 'Belum dikenal' atau 'Tidak mendaftar'. Tetapi tidak ada alasan untuk menempatkan Nulls sebagai yang pertama atau terakhir. Jika kita tidak tahu nilai sebenarnya, maka itu bisa kecil atau besar.

Saya pikir standar untuk menentukan perilaku yang diinginkan Nulls selama penyortiran, adalah:

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

Sayangnya SQL-Server belum mengadopsi sintaks ini. Jika saya tidak salah, PostgreSQL dan Oracle memilikinya.

Satu solusi:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

Solusi lain yang perlu penyesuaian tergantung pada tipe data - tetapi tidak akan terbentuk dengan baik, karena tidak dapat menggunakan indeks pada (test):

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer
6
ypercubeᵀᴹ

Saya tidak tahu mengapa dilakukan dengan cara itu, tetapi menurut definisi NULLS tidak dapat dibandingkan dengan non-NULLS, sehingga mereka harus pergi di awal atau di akhir (jawaban Markus mencakup ini dalam lebih banyak detail).

Untuk mendapatkan perilaku yang Anda inginkan - Sejauh yang saya tahu tidak ada opsi penyortiran untuk menempatkan nol terakhir, jadi Anda harus menggabungkannya dengan menggunakan kolom yang dikomputasi untuk memaksa mereka bertahan. Namun, dalam SQL Server Anda tidak dapat memesan dengan kolom yang dihitung (CASE WHEN ...) saat data Anda berisi satu set operator (UNION ALL). Begitu:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

Akan bekerja untuk menyortir null yang terakhir. Jika Anda harus menggunakan UNION (atau EXCEPT atau INTERSECTS) untuk menghasilkan kumpulan data Anda, maka buang data Anda ke tabel sementara seperti di atas.

3
Simon Righarts

Jika Anda berurusan dengan angka, Anda juga dapat menggunakan

ORDER BY -test DESC

NULL adalah nilai serendah mungkin, oleh karena itu DESC menempatkannya di akhir. Sementara itu nilai bukan nol memiliki tanda terbalik sehingga DESC sebenarnya adalah ASC pada nilai riil. Ini harus lebih cepat dari CASE dan saya mengira bahwa pengoptimal permintaan juga dapat menggunakan indeks pada kolom test.

0
Luca