Sorgularda Cross Join ve Self Join – Bölüm 14
Bu bölümde bazı özel senaryolarda faydalı olan farklı join türleri hakkında bilgi edineceğiz.
Cross Join
Cross join sorguları, daha önce öğrendiğimiz gibi, kaçınılması gereken bir Kartezyen oluşturur. ANSI SQL-89 syntax’ı ile bu join’i oluşturmak için bir syntax görmüş olsanız da bunun ANSI SQL-92 ile nasıl ve neden yapıldığını görmediniz. Bu bölümde cross join ve Kartezyen ürüne tekrar bakacağız.
Doğrudan bir Kartezyen oluşturmak için CROSS JOIN ifadesini kullanabilirsiniz.
Input satır kombinasyonları ile bir sonuç kümesi oluşturulacaktır:
SELECT ...
FROM table1 AS t1 CROSS JOIN table2 AS t2;
Çıktı, genel olarak olarak istenen bir çıktı olmasa da cross join yazmak için birkaç pratik yol bulunmaktadır:
- Bir aralıktaki her değer için bir satıra sahip olan sayı tablosu oluşturmak.
- Test amaçlı büyük boyutta veri üretmek. Kendi kendisine cross join ile eklendiğinde 100 satır içeren bir tablodan kolayca 10.000 satırlık başka bir tablo oluşturabilir.
Cross Join Syntax
Cross join ile sorgu yazarken, aşağıdakileri göz önünde bulundurmakta fayda vardır:
- Hiçbir satır eşleştirmesi yapılmadığı için ON ifadesini kullanmaya gerek yoktur.
- ANSI SQL-92 syntax’ını kullanmak için input tablo isimlerini CROSS JOIN ifadesiyle ayırmak gerekir.
Cross Join Örnekleri
İki input kümesinin tüm kombinasyonlarını oluşturan bir CROSS JOIN örneği aşağıda verilmiştir. Dokuz çalışanın adı ve soyadı alınarak 81 kombinasyona sahip çıktı üretilmektedir:
SELECT e1.firstname, e2.lastname
FROM HR.Employees e1 CROSS JOIN
HR.Employees e2;
Self Joins
Şimdiye kadar gördüğümüz join örneklerinde birden fazla tablo kullanılmıştır. Aynı tabloda depolanan verileri karşılaştırmanız ve tablodan veri çekmeniz gereken senaryolar olabilir. Örneğin klasik bir insan kaynakları uygulamasında bir Çalışanlar tablosu, çalışanının satırında amiri hakkında bilgi içerebilir. Her yönetici aynı zamanda bir çalışan olarak listelenir. Çalışan bilgilerini almak ve ilgili amir ile eşleştirmek için sorgunuzdaki bir tabloyu iki kez kullanabilir, tabloyu kendi kendine ekleyebilirsiniz.
Bir tablodaki satırları birbirleriyle karşılaştırmak isteyeceğiniz başka senaryolar da olabilir. Görüldüğü üzere T-SQL kullanarak aynı satırdaki sütunları karşılaştırmak oldukça kolay, ancak farklı satırlardaki değerlerin (aynı tabloda içerisinde, başlama süresini depolayan bir satırla buna karşılık gelen bitiş zamanını depolayan başka bir satır gibi) nasıl karşılaştırılacağı biraz karışıktır.
Bu gibi işlemleri gerçekleştirmek için aşağıdaki yönergelere dikkat etmek gereklidir:
- FROM deyimiyle aynı tablonun iki örneğini alın ve inner veya outer join kullanarak bunları birleştirin.
- Aynı tablo için iki faklı takma ad oluşturun. En az birinin takma adı olmalı.
- Aynı tablodan ayrı sütunları kullanarak bir filtre oluşturmak için ON deyimini kullanın.
Bir sonraki bölümde daha yakından inceleyeceğiniz aşağıdaki örnek, bu yönergeleri uygulamaktadır.
Bu sorguda çalışanlar ve eşleşen yönetici bilgileri, self join gerçekleştirilen Employees tablosundan alınmıştır:
SELECT e.empid, e.lastname AS empname, e.title, e.mgrid, m.lastname AS mgrname
FROM HR.Employees AS e
JOIN HR.Employees AS m
ON e.mgrid=m.empid;
Aşağıdaki sonuçlar dönecektir:
empid empname title mgrid mgrname
----- ------------ --------------------- ----- -------
2 Funk Vice President, Sales 1 Davis
3 Lew Sales Manager 2 Funk
4 Peled Sales Representative 3 Lew
5 Buck Sales Manager 2 Funk
6 Suurs Sales Representative 5 Buck
7 King Sales Representative 5 Buck
8 Cameron Sales Representative 3 Lew
9 Dolgopyatova Sales Representative 5 Buck
Self Join Örnekleri
Aşağıda self join örnekleri verilmiştir.
Bu sorgu, eğer bir yönetici varsa, her çalışanın ve yöneticisinin adıyla birlikte tüm çalışanları döndürür (inner join). Listede yöneticisi bulunmayan çalışan bilgileri sonuçlarda olmayacaktır:
SELECT e.empid, e.lastname AS
empname,e.title,e.mgrid, m.lastname AS mgrname
FROM HR.Employees AS e
JOIN HR.Employees AS m
ON e.mgrid = m.empid;
Bu sorgu, tüm çalışanları her bir yöneticinin adıyla döner (outer join):
SELECT e.empid, e.lastname AS empname, e.title, e.mgrid, m.lastname AS mgrname
FROM HR.Employees AS e
LEFT OUTER JOIN HR.Employees AS m
ON e.mgrid = m.empid;