Sorgu sorununu kullanarak çözdüm ... row_number() over (partition by
... neden birleştirmelerde null değerleri olan sütunları kullanamadığımıza dair daha genel bir soru. Bir null için bir null değeri null değerine eşit olamaz?
Sorgu sorununu kullanarak çözdüm ... row_number() over (partition by
... neden birleştirmelerde null değerleri olan sütunları kullanamadığımıza dair daha genel bir soru. Bir null için bir null değeri null değerine eşit olamaz?
Yanıtlar:
Bir null için bir null değeri null değerine eşit olamaz?
Oracle'a bunu yapmasını söyleyin:
select *
from one t1
join two t2 on coalesce(t1.id, -1) = coalesce(t2.id, -1);
(Standart SQL'de t1.id is not distinct from t2.id
sıfır güvenlikli bir eşitlik operatörü almak için kullanabileceğinizi , ancak Oracle'ın bunu desteklemediğini unutmayın)
Ancak bu yalnızca değiştirme değeri (yukarıdaki örnekte -1) tabloda görünmüyorsa işe yarar. Sayılar için böyle bir "sihirli" değer bulmak mümkün olabilir , ancak karakter değerleri için çok zor olacaktır (özellikle Oracle da boş bir dizgiyi tedavi ettiği için null
)
Artı: hiçbir dizin id
sütunları kullanılacaktır (eğer olabilir bir fonksiyon bazlı endeks tanımlamak coalesce()
ifade rağmen).
Sihirli değerler olmadan tüm türler için çalışan başka bir seçenek:
on t1.id = t2.id or (t1.id is null and t2.id is null)
Ama asıl soru şu: bu mantıklı mı?
Aşağıdaki örnek verileri göz önünde bulundurun:
Birinci masa
id
----
1
2
(null)
(null)
Tablo iki
id
----
1
2
(null)
(null)
(null)
Birleştirmede hangi null değerlerin birleşimi seçilmelidir? Yukarıdaki örneğim, tüm boş değerler için çapraz birleştirme gibi bir şeyle sonuçlanacaktır.
T1_ID | T2_ID
-------+-------
1 | 1
2 | 2
(null) | (null)
(null) | (null)
(null) | (null)
(null) | (null)
(null) | (null)
(null) | (null)
Alternatif INTERSECT
olarak, eşitlik operatörü olarak kullanarak iki null değerinin birbiriyle eşleşmesini sağlayabilirsiniz :
SELECT
*
FROM
t1
INNER JOIN t2
ON EXISTS (SELECT t1.ID FROM DUAL INTERSECT SELECT t2.ID FROM DUAL)
;
Bir örnek için bu DBFiddle demosuna bakın .
Tabii ki, bu oldukça ağız dolusu görünüyor, ancak aslında BriteSponge'un önerisinden çok daha uzun değil . Ancak, eğer cezai affederseniz, daha önce bahsedilenlerin standart olarak, yani IS NOT DISTINCT FROM
operatör olan, henüz Oracle'da desteklenmeyen kısa özlüğe uyması kesinlikle bir eşleşme değildir.
Tam olarak söylemek gerekirse, fonksiyonun SYS_OP_MAP_NONNULL
artık 12c belgelerinde belgelendiği gibi boş değerleri karşılaştırmak için güvenle kullanılabileceğinden bahsedeceğim . Bu, Oracle'ın rasgele kaldırıp kodunuzu kırmayacağı anlamına gelir.
SELECT *
FROM one t1
JOIN two t2
ON SYS_OP_MAP_NONNULL(t1.id) = SYS_OP_MAP_NONNULL(t2.id)
Avantajı 'sihirli' sayı problemiyle karşılaşmamanızdır.
Oracle belgelerindeki referans Temel Materyalleştirilmiş Görünümler - Materyalleştirilmiş Görünümler için Dizin Seçme konusudur .
Kod çözme kullanarak null değerleri birleştirebilirsiniz:
on decode(t1.id, t2.id, 1, 0) = 1
decode
null değerlerine eşit davranır, dolayısıyla bu "sihirli" sayılar olmadan çalışır. İki sütun aynı veri türüne sahip olmalıdır.
En okunabilir kodu yapmayacak, ancak muhtemelen t1.id = t2.id or (t1.id is null and t2.id is null)
Birleştirmelerde null değerleri neden kullanamıyorsunuz? Oracle'da aşağıdakilerin ikisi de doğru olarak değerlendirilmez:
NULL = NULL
NULL <> NULL
Elimizdeki bu yüzden IS NULL
/ IS NOT NULL
null değerleri denetlemek için.
Bunu test etmek için şunları yapabilirsiniz:
SELECT * FROM table_name WHERE NULL = NULL
Birleşmeler bir boole koşulunu değerlendiriyor ve bunları farklı şekilde çalışacak şekilde programlamıyorlardı. Birleştirme koşuluna birden çok işaret koyabilir ve başka koşullar ekleyebilirsiniz; sadece bir boole ifadesi olarak değerlendirir.
Sanırım bir sıfır, tutarlılık uğruna birleştirme içindeki sıfırdan eşit olamaz. Karşılaştırma operatörünün olağan davranışına meydan okuyacaktır.
NULL = anything
sonuçları NULL
SQL standardı öyle diyor çünkü. Bir satır birleştirme koşulunu yalnızca ifade doğruysa karşılar.
İlişkisel veritabanlarının çoğunda null değeri bilinmeyen olarak kabul edilir. Tüm HEX sıfırları ile karıştırılmamalıdır. bir şey null (bilinmiyor) içeriyorsa, onu karşılaştıramazsınız.
Unknown = Known False
Unknown = Unknown False
Unknown >= Known False
Known >= Unknown False
Bu, boole ifadesinde bir işlenen olarak null değeriniz olduğunda, diğer bölüm her zaman doğru olacaktır.
Geliştiriciler tarafından null'a karşı genel nefretin aksine, null'un yeri vardır. Bilinmeyen bir şey varsa null kullanın.
UNKNOWN
değil FALSE
;)
where (a = b or (a is null and b is null))
sys_op_map_nonnull