NULL'lar neden önce sıralanır?


20

Neden bir sütunda NULL değerimiz olduğunda ve artan değere göre sıraladığımızda, NULL'ları önce sıralarsak?

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

sonuç

NULL
1
2
3
4

NULL'un "Belirsiz" veya olası "Bilinmeyen" anlamına geldiğini düşünmeye devam ediyorum. Bu doğruysa, değer diğer tüm değerlerden daha büyük olabileceğinden, son olarak sıralamazlar mı? (Yoksa bu bir yerde bir sıralama seçeneği midir?)

SQL Server 2008R2'deyim, ancak bunun tüm SQL Sunucularında ve muhtemelen tüm RDBMS'lerde doğru olduğundan şüpheliyim.


1
Oracle en son listeler. Bu beni bir kez mahvetti, SQL Server gibi davranması gerektiğine inanıyordu.
Andrei Rînea

2
"Bu doğruysa, değer diğer tüm değerlerden daha büyük olabileceğinden, son sıralamazlar". Değer, diğer tüm değerlerden daha düşük olabilir. Bana göre, null gibi bir falsey değerinin alt uçta olması sezgiseldir. Pratikte, pratikte, descen büyük veya en yeni şeyleri göstermek için sıralamayı kullanmak istersiniz , bu durumda null şeylerin sonuncusudur.
mahemoff

Veritabanı, söylediklerinizi yapar. Verilerinizin null içerdiğini biliyorsanız ve verileri belirli bir şekilde sıralamak için bazı ticari nedenleriniz varsa, bunu sorguda veya verileri işleyen / görüntüleyen kod / görünümde belirtmeniz gerekir. Asla varsayılan veritabanı davranışına göre sıralama bırakmayın.
gerekli olmayan

Yanıtlar:


19

BOL : NULL değeri, değerin bilinmediğini gösterir. NULL değeri boş veya sıfır değerinden farklıdır. İki boş değer eşit değildir. İki null değer arasındaki veya bir NULL ile başka bir değer arasındaki karşılaştırmalar, her NULL değerinin bilinmediği için bilinmeyen döndürür.

NULL, bilinmeyen anlamına gelir. Başka bir yorum geçerli değil.

Bu doğruysa, değer diğer tüm değerlerden daha büyük olabileceğinden, son olarak sıralamazlar mı?

Hiçbir yoktur olabilir . Potansiyel bir değer yoktur . Bilinmeyen bilinmiyor bilinmiyor.

Neden ilk önce göründüğüne ilişkin olarak, bu yayınlanmış SQL standartları tarafından karşılanmamıştır ve maalesef, RDBMS satıcısının takdirine bırakılmıştır:

Wikipedia : SQL standardı, Nulls için varsayılan bir sıralama düzenini açıkça tanımlamıyor. Bunun yerine, uyumlu sistemlerde, sırasıyla ORDER BY listesinin NULLS FIRST veya NULLS LAST yan tümceleri kullanılarak tüm veri değerlerinden önce veya sonra Null sıralanabilir. Ancak, tüm DBMS satıcıları bu işlevi yerine getirmez. Bu işlevi uygulamayan satıcılar DBMS’de Null sıralama için farklı işlemler belirleyebilir.


Yani bu bir yargılama çağrısı. Bu çok mantıklı. Teşekkürler!
Richard

6

Bunu doğru NULL'uygulayarak Değil' 'indeterminant' veya 'Uknownn' ya da 'henüz bilinmemektedir' ya anlamına gelebilir. Ancak Null'ları birinci veya sonuncuya koymak için hiçbir neden yoktur. Gerçek değerleri bilmiyorsak, küçük veya büyük olabilir.

Ben sıralama sırasında Nulls istenen davranışını belirlemek için standart olduğunu düşünüyorum:

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

Ne yazık ki SQL-Server bu sözdizimini henüz kabul etmedi. Yanılmıyorsam PostgreSQL ve Oracle var.

Bir çözüm:

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

Veri türü olarak ayarlama ihtiyacı Başka bir çözüm - olmaz preform iyi, bir dizin kullanamazsınız olarak değil (test):

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

Bu sayede SİPARİŞ TARAFINDAN SİPARİŞ (test, 2147483647) SQL server İndeks kullanamaz.
Ardalan Shahgholi

3

Neden bu şekilde yapıldığını bilmiyorum , ancak tanım gereği NULLS, NULL olmayanlarla karşılaştırılamaz, bu yüzden ya başlangıçta ya da sonunda gitmek zorunda kalırlar (Mark'ın cevabı bunu çok daha ayrıntılı olarak kapsar).

İstediğiniz davranışı elde etmek için - Bildiğim kadarıyla, null'ları sonlandırmak için bir sıralama seçeneği yoktur, bu yüzden onları en son zorlamak için hesaplanmış bir sütun kullanarak bodge yapmak zorundasınız. Ancak, SQL Server'da CASE WHEN ..., verileriniz bir küme operatörü ( UNION ALL) içerdiğinde hesaplanan bir sütuna ( ) göre sipariş veremezsiniz . Yani:

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

Son olarak null'ları sıralamak için çalışacaktır. Veri kümenizi oluşturmak için kullanmak UNION(veya EXCEPTveya INTERSECTS) kullanmak zorundaysanız , verilerinizi yukarıdaki gibi geçici bir tabloya boşaltın.


... veya UNIONed çıktısını türetilmiş bir tablo olarak kullanabilirsiniz.
Andriy M

0

Numaralarla uğraşıyorsanız,

ORDER BY -test DESC

NULLolası en düşük değerlerdir, bu nedenle DESConları sonuna koyar. Bu arada, null olmayan değerler ters çevrilmiş işarete sahiptir, bu yüzden gerçek değerler üzerinde DESCbir ASCdeğerdir. Bu daha hızlı olmalı CASEve sorgu optimizer testsütununda da dizinleri kullanabilirsiniz varsayalım .


3
Hayır, sıralama için bir dizin kullanamazsınız. Hesaplanan ifadede bir dizin yoksa (- test).
ypercubeᵀᴹ

1
Zekice, sadece sayısal verilerle sınırlı olsa da (yine de OP örneğine uygun). Bunun gerçekten CASE kullanmaktan daha hızlı olup olmayacağından emin değilim, ancak bir dizin kullanmayacağından eminim (@ ypercubeᵀᴹ dediği sürece - ama o zaman bir CASE ifadesi aynı şekilde dizine alınabilir).
Andriy M,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.