Takip et

SQL IN ve SQL NOT IN Operatörleri: Kapsamlı Bir Teknik İnceleme

SQL IN ve SQL NOT IN Operatörleri: Kapsamlı Bir Teknik İnceleme SQL’de veri filtreleme ve sorgulama, veritabanı yönetiminin temel taşlarından biridir.

SQL IN ve SQL NOT IN Operatörleri: Kapsamlı Bir Teknik İnceleme

SQL’de veri filtreleme ve sorgulama, veritabanı yönetiminin temel taşlarından biridir. Bu filtreleme işlemlerinde en sık kullanılan ve en güçlü operatörlerden ikisi IN ve NOT IN operatörleridir. Bu makalede, bu iki operatörün ne olduğunu, nasıl çalıştıklarını, kullanım alanlarını, performans etkilerini ve alternatiflerini derinlemesine inceleyeceğiz.

SQL IN Operatörü

IN operatörü, bir sütundaki değerin, belirtilen bir değer listesindeki herhangi bir değere eşit olup olmadığını kontrol etmek için kullanılır. Temel olarak, bir sütun için birden fazla OR koşulunu daha okunabilir ve özlü bir şekilde ifade etmenin bir yoludur.

IN Operatörünün Sözdizimi

IN operatörünün genel sözdizimi şu şekildedir:

SELECT sütun1, sütun2, ...
FROM tablo_adı
WHERE sütun_adı IN (değer1, değer2, değer3, ...);

Burada:
sütun1, sütun2, ...: Sorgulanacak sütunların adlarıdır.
tablo_adı: Verilerin çekileceği tablonun adıdır.
sütun_adı: Kontrol edilecek sütunun adıdır.
değer1, değer2, değer3, ...: sütun_adı‘nın karşılaştırılacağı değerlerin listesidir. Bu değerler aynı veri tipinde olmalıdır.

IN Operatörünün Çalışma Mantığı

IN operatörü, WHERE yan tümcesinde belirtilen sütunun değerini, parantez içindeki değer listesiyle karşılaştırır. Eğer sütunun değeri listedeki herhangi bir değere eşitse, ilgili satır sorgu sonucuna dahil edilir.

Örneğin, aşağıdaki sorgu, musteriler tablosundan sehir sütunu ‘Ankara’, ‘İstanbul’ veya ‘İzmir’ olan tüm müşterileri getirir:

SELECT musteri_id, ad, soyad, sehir
FROM musteriler
WHERE sehir IN ('Ankara', 'İstanbul', 'İzmir');

Bu sorgu, aşağıdaki gibi yazılmış bir sorguyla tamamen aynı sonucu verir:

SELECT musteri_id, ad, soyad, sehir
FROM musteriler
WHERE sehir = 'Ankara' OR sehir = 'İstanbul' OR sehir = 'İzmir';

Ancak IN operatörü, özellikle liste uzun olduğunda, sorguyu daha okunabilir hale getirir.

IN Operatörünün Kullanım Alanları

IN operatörü çeşitli senaryolarda faydalıdır:

* Belirli Değerlere Sahip Kayıtları Getirme: Yukarıdaki örnekte olduğu gibi, belirli bir sütunda önceden tanımlanmış bir dizi değere sahip kayıtları çekmek için kullanılır.
* Alt Sorgularla Birlikte Kullanım: IN operatörü, bir alt sorgunun döndürdüğü değerlerle de kullanılabilir. Bu, daha karmaşık veri filtreleme senaryolarında çok güçlü bir araçtır.

Örneğin, belirli bir ürün kategorisindeki tüm siparişleri getirmek isteyebilirsiniz:

SELECT siparis_id, musteri_id, siparis_tarihi
    FROM siparisler
    WHERE urun_id IN (SELECT urun_id FROM urunler WHERE kategori = 'Elektronik');

Bu sorgu, önce urunler tablosundan ‘Elektronik’ kategorisindeki ürünlerin urun_id‘lerini alır ve ardından siparisler tablosunda bu urun_id‘lere sahip siparişleri getirir.

* Çoklu Sütun Karşılaştırmaları: Bazı SQL lehçeleri (örneğin PostgreSQL, MySQL 8.0+) IN operatörünü birden fazla sütunla birlikte kullanmaya izin verir. Bu, bir satırın birden fazla sütunundaki değerlerin, belirtilen bir tuple (değer kümesi) listesindeki bir tuple ile tam olarak eşleşip eşleşmediğini kontrol etmek için kullanılır.

SELECT *
    FROM siparis_detaylari
    WHERE (urun_id, miktar) IN ((101, 5), (105, 2), (110, 1));

Bu sorgu, urun_id‘si 101 ve miktar‘ı 5 olan VEYA urun_id‘si 105 ve miktar‘ı 2 olan VEYA urun_id‘si 110 ve miktar‘ı 1 olan kayıtları getirir.

IN Operatörünün Avantajları

* Okunabilirlik: Birden fazla OR koşulunu daha anlaşılır hale getirir.
* Kısalık: Uzun koşul listeleri için daha az kod yazmayı sağlar.
* Esneklik: Sabit değer listeleriyle veya dinamik olarak üretilen alt sorgularla kullanılabilir.

IN Operatörünün Dezavantajları ve Dikkat Edilmesi Gerekenler

* Performans (Büyük Listeler): Çok büyük değer listeleri kullanıldığında, IN operatörü performans sorunlarına yol açabilir. Veritabanı, her bir değeri listedeki değerlerle karşılaştırmak zorunda kalır. Bu durumda, bazı veritabanı sistemleri için EXISTS veya JOIN gibi alternatifler daha verimli olabilir.
* NULL Değerler: IN operatörü NULL değerlerle karşılaştırıldığında beklenmedik sonuçlar verebilir. IN listesinde NULL varsa ve sütun değeri NULL ise, bu durum UNKNOWN olarak değerlendirilir ve satır dahil edilmez. Eğer sütun değeri NULL ise ve listede NULL yoksa da aynı durum geçerlidir.

-- Bu sorgu, 'sehir' NULL olan müşterileri GETİRMEZ
    SELECT * FROM musteriler WHERE sehir IN ('Ankara', 'İstanbul', NULL);

Eğer NULL değerleri de dahil etmek istiyorsanız, açıkça OR sehir IS NULL eklemeniz gerekir.

SQL NOT IN Operatörü

NOT IN operatörü, IN operatörünün tam tersi şekilde çalışır. Bir sütundaki değerin, belirtilen bir değer listesindeki hiçbir değere eşit olup olmadığını kontrol etmek için kullanılır. Bu da, birden fazla AND koşulunu daha özlü bir şekilde ifade etmenin bir yoludur.

NOT IN Operatörünün Sözdizimi

NOT IN operatörünün genel sözdizimi şu şekildedir:

SELECT sütun1, sütun2, ...
FROM tablo_adı
WHERE sütun_adı NOT IN (değer1, değer2, değer3, ...);

Burada parametreler IN operatöründeki ile aynı anlama gelir.

NOT IN Operatörünün Çalışma Mantığı

NOT IN operatörü, WHERE yan tümcesinde belirtilen sütunun değerini, parantez içindeki değer listesiyle karşılaştırır. Eğer sütunun değeri listedeki hiçbir değere eşit değilse, ilgili satır sorgu sonucuna dahil edilir.

Örneğin, aşağıdaki sorgu, musteriler tablosundan sehir sütunu ‘Ankara’, ‘İstanbul’ veya ‘İzmir’ olmayan tüm müşterileri getirir:

SELECT musteri_id, ad, soyad, sehir
FROM musteriler
WHERE sehir NOT IN ('Ankara', 'İstanbul', 'İzmir');

Bu sorgu, aşağıdaki gibi yazılmış bir sorguyla tamamen aynı sonucu verir:

SELECT musteri_id, ad, soyad, sehir
FROM musteriler
WHERE sehir <> 'Ankara' AND sehir <> 'İstanbul' AND sehir <> 'İzmir';

Ancak NOT IN operatörü, özellikle liste uzun olduğunda, sorguyu daha okunabilir hale getirir.

NOT IN Operatörünün Kullanım Alanları

NOT IN operatörü de çeşitli senaryolarda faydalıdır:

Belirli Değerlere Sahip Olmayan Kayıtları Getirme: Yukarıdaki örnekte olduğu gibi, belirli bir sütunda önceden tanımlanmış bir dizi değere sahip olmayan* kayıtları çekmek için kullanılır.
* Alt Sorgularla Birlikte Kullanım: NOT IN operatörü de alt sorgularla birlikte kullanılabilir.

Örneğin, belirli bir ürün kategorisinde olmayan siparişleri getirmek isteyebilirsiniz:

SELECT siparis_id, musteri_id, siparis_tarihi
    FROM siparisler
    WHERE urun_id NOT IN (SELECT urun_id FROM urunler WHERE kategori = 'Elektronik');

Bu sorgu, önce urunler tablosundan ‘Elektronik’ kategorisindeki ürünlerin urun_id‘lerini alır ve ardından siparisler tablosunda bu urun_id‘lere sahip olmayan siparişleri getirir.

* Dışlayıcı Filtreleme: Bir grup kaydı dışarıda bırakmak istediğinizde çok kullanışlıdır.

NOT IN Operatörünün Dezavantajları ve Dikkat Edilmesi Gerekenler

NOT IN operatörünün en önemli ve en çok karşılaşılan sorunu, alt sorgu veya değer listesi NULL bir değer içerdiğinde ortaya çıkar.

NULL Değerler ve Alt Sorgular: Eğer NOT IN operatörünün kullandığı değer listesi (ister sabit liste ister alt sorgu sonucu olsun) herhangi bir NULL değer içeriyorsa, sorgu hiçbir satır döndürmeyebilir. Bunun nedeni şudur: NOT IN operatörü, sütun değerinin listedeki tüm* değerlere eşit olmamasına dayanır. Eğer listede NULL varsa, karşılaştırma şöyle olur: sutun_degeri <> NULL. NULL ile yapılan herhangi bir karşılaştırma (eşittir, eşit değildir, büyüktür, küçüktür vb.) her zaman UNKNOWN sonucunu verir. NOT IN operatörü UNKNOWN sonuçlarını FALSE olarak değerlendirir. Dolayısıyla, listede bir NULL olması, tüm karşılaştırmaları FALSE yapar ve sonuç olarak hiçbir satır dönmez.

Örnek Senaryo:

-- Diyelim ki urunler tablosunda urun_id'si 5 olan ürünün kategorisi NULL
    SELECT *
    FROM siparisler
    WHERE urun_id NOT IN (SELECT urun_id FROM urunler WHERE kategori = 'Elektronik' OR kategori IS NULL);

Bu sorgu, urunler tablosundan ‘Elektronik’ kategorisindeki ürün ID’lerini veya kategori‘si NULL olan ürün ID’lerini alır. Eğer kategori‘si NULL olan bir ürün ID’si varsa, alt sorgu NULL döndürecektir. Bu durumda NOT IN operatörü, hiçbir satır döndürmeyecektir.

Çözüm: NOT IN operatörünü alt sorgularla kullanırken, alt sorgunun NULL değer döndürmediğinden emin olmanız veya NULL değerleri filtrelemeniz çok önemlidir.

SELECT siparis_id, musteri_id, siparis_tarihi
    FROM siparisler
    WHERE urun_id NOT IN (SELECT urun_id FROM urunler WHERE kategori = 'Elektronik' AND urun_id IS NOT NULL);

Sabit listelerde de NULL değerler benzer sorunlara yol açar:

-- Bu sorgu, 'sehir' NULL olan müşterileri de GETİRMEYEBİLİR,
    -- hatta genellikle hiçbir şey GETİRMEYEBİLİR.
    SELECT * FROM musteriler WHERE sehir NOT IN ('Ankara', 'İstanbul', NULL);

* Performans: IN operatöründe olduğu gibi, çok büyük değer listeleri NOT IN operatörünün performansını olumsuz etkileyebilir.

IN ve NOT IN Operatörlerinin Performans Etkileri ve Alternatifleri

IN ve NOT IN operatörleri, özellikle küçük ve orta ölçekli veri kümelerinde ve sabit değer listeleriyle kullanıldığında oldukça verimli olabilir. Ancak, büyük veri kümelerinde veya alt sorgularla kullanıldığında performans sorunları yaşanabilir.

Performans Sorunları ve Nedenleri

1. Listelerin Boyutu: Operatörler, listedeki her bir değeri sütunla karşılaştırmak zorundadır. Liste ne kadar uzun olursa, karşılaştırma sayısı o kadar artar ve sorgu o kadar yavaşlar.
2. Alt Sorgu Optimizasyonu: Veritabanı optimizleyicisinin alt sorguları nasıl işlediği performansı büyük ölçüde etkiler. Bazı durumlarda, veritabanı alt sorguyu her satır için tekrar çalıştırabilir (correlated subquery), bu da ciddi performans düşüşlerine neden olur.
3. İndeks Kullanımı: IN ve NOT IN operatörleri, eğer sütun üzerinde uygun bir indeks varsa, bu indeksi kullanabilir. Ancak, çok geniş değer listeleri veya alt sorgular, indeksin verimli bir şekilde kullanılmasını engelleyebilir.

Alternatifler

Performans sorunlarını gidermek veya daha iyi performans elde etmek için IN ve NOT IN operatörlerine alternatifler bulunmaktadır:

1. JOIN Operatörü:
* IN için Alternatif: INNER JOIN veya LEFT JOIN operatörleri, IN operatörü ile aynı sonucu verebilir ve genellikle daha iyi performans gösterir. Özellikle alt sorgularla IN kullanmak yerine, bu alt sorguyu ayrı bir tablo gibi düşünerek JOIN yapmak daha verimli olabilir.

-- IN ile yapılan sorgu
        SELECT m.*
        FROM musteriler m
        WHERE m.sehir IN ('Ankara', 'İstanbul', 'İzmir');

        -- JOIN ile yapılan eşdeğer sorgu
        SELECT m.*
        FROM musteriler m
        JOIN sehirler s ON m.sehir = s.sehir_adi
        WHERE s.sehir_adi IN ('Ankara', 'İstanbul', 'İzmir');
        -- VEYA daha yaygın olarak:
        SELECT m.*
        FROM musteriler m
        WHERE m.sehir = 'Ankara' OR m.sehir = 'İstanbul' OR m.sehir = 'İzmir';
        -- VEYA
        SELECT m.*
        FROM musteriler m
        WHERE m.sehir IN (SELECT sehir_adi FROM sehirler WHERE sehir_adi IN ('Ankara', 'İstanbul', 'İzmir'));

Daha karmaşık IN alt sorguları için JOIN daha da avantajlıdır:

-- IN ile yapılan sorgu
        SELECT s.*
        FROM siparisler s
        WHERE s.urun_id IN (SELECT u.urun_id FROM urunler u WHERE u.kategori = 'Elektronik');

        -- JOIN ile yapılan eşdeğer sorgu
        SELECT s.*
        FROM siparisler s
        JOIN urunler u ON s.urun_id = u.urun_id
        WHERE u.kategori = 'Elektronik';

Bu JOIN versiyonu genellikle daha hızlıdır çünkü veritabanı, iki tabloyu birleştirerek ve ardından filtreleyerek daha optimize bir plan oluşturabilir.

* NOT IN için Alternatif: LEFT JOIN ve IS NULL kontrolü veya NOT EXISTS operatörü NOT IN‘in iyi alternatifleridir.

-- NOT IN ile yapılan sorgu
        SELECT m.*
        FROM musteriler m
        WHERE m.sehir NOT IN ('Ankara', 'İstanbul', 'İzmir');

        -- LEFT JOIN ile yapılan eşdeğer sorgu
        SELECT m.*
        FROM musteriler m
        LEFT JOIN sehirler s ON m.sehir = s.sehir_adi AND s.sehir_adi IN ('Ankara', 'İstanbul', 'İzmir')
        WHERE s.sehir_adi IS NULL;

Bu LEFT JOIN yaklaşımı, NOT IN‘in NULL değerlerle ilgili sorunlarını yaşamaz ve genellikle daha öngörülebilir performans sunar.

Alt sorgularla NOT IN kullanırken:

-- NOT IN ile yapılan sorgu (potansiyel NULL sorunu)
        SELECT s.*
        FROM siparisler s
        WHERE s.urun_id NOT IN (SELECT u.urun_id FROM urunler u WHERE u.kategori = 'Elektronik');

        -- NOT EXISTS ile yapılan eşdeğer sorgu (daha güvenli ve genellikle daha hızlı)
        SELECT s.*
        FROM siparisler s
        WHERE NOT EXISTS (
            SELECT 1
            FROM urunler u
            WHERE u.urun_id = s.urun_id AND u.kategori = 'Elektronik'
        );

NOT EXISTS, alt sorgunun eşleşen bir kayıt bulup bulmadığını kontrol eder. Eğer eşleşen bir kayıt bulunamazsa, NOT EXISTS TRUE döndürür. Bu, NULL değerlerinden etkilenmez ve genellikle NOT IN‘den daha iyi performans gösterir.

2. EXISTS Operatörü:
* EXISTS operatörü, bir alt sorgunun herhangi bir satır döndürüp döndürmediğini kontrol eder. Genellikle IN operatörüne bir alternatif olarak kullanılır.
* IN ile:

-- IN ile yapılan sorgu
        SELECT m.*
        FROM musteriler m
        WHERE m.sehir IN ('Ankara', 'İstanbul', 'İzmir');

        -- EXISTS ile yapılan eşdeğer sorgu
        SELECT m.*
        FROM musteriler m
        WHERE EXISTS (
            SELECT 1
            FROM (VALUES ('Ankara'), ('İstanbul'), ('İzmir')) AS sehirler(sehir_adi)
            WHERE m.sehir = sehirler.sehir_adi
        );

Bazı veritabanı sistemlerinde, özellikle alt sorgu karmaşıksa, EXISTS IN‘den daha iyi performans gösterebilir çünkü EXISTS ilk eşleşmeyi bulduğunda alt sorguyu çalıştırmayı durdurabilir.

Özet ve En İyi Uygulamalar

IN ve NOT IN operatörleri, SQL’de veri filtreleme için güçlü ve kullanışlı araçlardır. Ancak, kullanımlarında dikkatli olunması gereken bazı önemli noktalar vardır, özellikle NULL değerler ve performans konusunda.

* Okunabilirlik İçin Kullanın: Küçük ve orta ölçekli sabit değer listeleriyle IN ve NOT IN kullanmak, sorguları daha okunabilir hale getirir.
* NULL Değerlere Dikkat Edin: Özellikle NOT IN operatörünü alt sorgularla kullanırken, alt sorgunun NULL değer döndürmediğinden emin olun. Aksi takdirde beklenmedik sonuçlar (genellikle boş küme) alabilirsiniz. NOT EXISTS bu tür durumlarda daha güvenli bir alternatiftir.
* Performans İçin Alternatifleri Değerlendirin: Büyük veri kümelerinde veya karmaşık alt sorgularda, JOIN veya EXISTS gibi alternatifleri değerlendirin. Veritabanı optimizasyon araçlarını (örneğin EXPLAIN komutu) kullanarak sorgularınızın performansını test edin ve en verimli yöntemi seçin.
* Sabit Listeler vs. Alt Sorgular: Sabit değer listeleriyle IN ve NOT IN genellikle iyi çalışır. Ancak, alt sorgularla kullanıldığında performans ve NULL sorunlarına daha dikkatli yaklaşılmalıdır.

Sonuç olarak, IN ve NOT IN operatörleri, SQL sorgularının vazgeçilmez bir parçasıdır. Bu operatörlerin nasıl çalıştığını, potansiyel tuzaklarını ve alternatiflerini anlamak, daha verimli, okunabilir ve doğru SQL sorguları yazmanıza yardımcı olacaktır. Her zaman sorgularınızı farklı senaryolarda test etmek ve veritabanınızın performans özelliklerini göz önünde bulundurmak en iyi uygulamadır.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Exit mobile version