Sorun: <> NULL'ı görmez
raw_signups tablosunda şehri “İstanbul” olmayan kayıtları saymak istiyorsun:
SELECT COUNT(*) AS adet FROM raw_signups WHERE city <> 'İstanbul';
Şehri NULL olan iki kayıt bu sayıya girmez. Çünkü NULL <> 'İstanbul' sonucu doğru değil bilinmiyordur ve WHERE yalnızca doğru olan satırları geçirir. İş kuralı “İstanbul dışındaki herkes” ise NULL satırlar da sayılmalıdır.
Taşınabilir çözüm
SELECT COUNT(*) AS adet FROM raw_signups WHERE city <> 'İstanbul' OR city IS NULL;
Her SQL türünde çalışır. İki sütunu karşılaştırırken (örneğin eski ve yeni değer) yazım uzar:
WHERE (a <> b) OR (a IS NULL AND b IS NOT NULL) OR (a IS NOT NULL AND b IS NULL)
IS DISTINCT FROM
SQL standardı bu karşılaştırma için ayrı bir operatör tanımlar. a IS DISTINCT FROM b, NULL'ı sıradan bir değer gibi ele alır:
| a | b | a <> b | a IS DISTINCT FROM b |
|---|---|---|---|
| 1 | 2 | doğru | doğru |
| 1 | 1 | yanlış | yanlış |
| 1 | NULL | bilinmiyor | doğru |
| NULL | NULL | bilinmiyor | yanlış |
Tersi IS NOT DISTINCT FROM'dur: iki NULL'ı da “eşit” sayar.
| SQL türü | “Farklı mı?” (NULL dahil) | “Aynı mı?” (NULL dahil) |
|---|---|---|
| PostgreSQL, BigQuery, SQL Server 2022+ | a IS DISTINCT FROM b | a IS NOT DISTINCT FROM b |
| MySQL | NOT (a <=> b) | a <=> b (NULL güvenli eşitlik) |
| Oracle | DECODE(a, b, 0, 1) = 1 (DECODE iki NULL'ı eşit sayar) | DECODE(a, b, 1, 0) = 1 |
| SQLite | a IS NOT b | a IS b |
<> bu değişikliği kaçırır.