JOIN Tipleri ve SQL Tablo Birleştirme İşlemleri

Veri birleştirme (data blending) işlemleri öncesinde Key, Primary Key, Unique Key ve Foreign Key Tanımlamaları ile başlayan ön yazılara JOIN kullanımı ve tablo birleştirme işlemleriyle devam ediyorum.

AA

Bu yazı içerisinde, örneklendirmeyi SQL ile vermiş olmamın nedeni R, Tableau ve komut satırı (command line) örneklerinden daha kolay pratik edilebilecek ortama sahip olması. Böylelikle, temel mantık diğer uygulamalarda da (ilişkisel veritabanı bağlamında) benzer olduğu için herhangi bir karmaşaya sebebiyet vermemiş olacağımı varsayıyorum. O halde, hızlıca konuya girelim.

JOIN

İlişkisel veritabanı (relational database) sistemlerinde sıklıkla kullanılan işlemlerden biri olan JOIN, table ve view gibi kaynakları ilişkilendiren, SELECT, INSERT INTO SELECT, SELECT INTO, UPDATE ve DELETE gibi işlemlerde FROM ile birlikte kullanılan ve bu şekilde tabloları (iki veya daha fazla) birleştiren ve sorgular temelinde bir sonuç tablosu (result table) oluşturmaya yarayan bir birleştiricidir. Bu işlemlerde, gereksinime göre farklı özelliklere sahip birleştiricilerden biri kullanılır; JOIN tipleri başlığı altında bu tiplerle ilgili detaylara ulaşabilirsiniz. Az önceki tanımlamada da bahsi geçtiği üzere JOIN birleştirmenin (sonuç tablosu oluşturma) yanı sıra SELECT ile iki ya da daha fazla tablo ilişkilendirilerek sorgulama yapılabilir. Ayrıca, SELF JOIN ile aynı tabloda da sorgulama yapmak mümkündür. Basit bir JOIN işlemi ile yukarıdaki tanımı örneklendirelim.

SELECT * FROM [table1] JOIN [table2] ON [table1.primary_key] = [table2.foreign_key];

Örneğe baktığımızda table1 ve table2 tablolarını ve bu tablolara ait primary_key ile foreign_key anahtarlarını görmekteyiz. Key, Primary Key, Unique Key ve Foreign Key Tanımlamaları başlıklı yazımda birincil (primary key) ve ikincil (foreign key) anahtarlarla ilgili tanımlalara yer vermiştim. Örneğe geri dönecek olursak, birleştirici olan kullanılan JOIN ile hangi tabloların birleştirileceğini belirtiyoruz; table1 ve table2. ON ifadesi ise bu tabloların hangi alanlar bağlamında ilişkilendirileceğini belirtir; table1.primary_key ile table2.foreign_key. Unutmatan, bu sütunların aldığı değerlerin (primary_key ve foreign_key) aynı veri tipine sahip olmaları gerekir. Tablo arasındaki işlemlerde genellikle = veya <> operatörleri ve yazım biçimini okunabilir ve pratik hale getirmek için alias kullanılır.

JOIN Tipleri

JOIN türlerini birleştirilen tablolardan hangisinin baskın olacağı veya hangisinden hangi alanların okunacağını belirtir ve bu amaçla tipler dahilinde çeşitli farklılıklar gösterirler. Aşağıda JOIN tipleriyle ilgili bilgilerin yanı sıra, bir durum senaryosu da ele alacağım ve bu sayede veriler üzerinde gerçek işlemler yapmış olacağız. Örnek işlemler için sqlfiddle veya farklı bir alternatif üzerinden ilerleyebilirsiniz1.

CREATE TABLE `attendance` (
  `attendance_ID` INT(11),
  `course_ID` INT(11),
  `employee_ID` INT(11),
  `courseDate` DATE
);

INSERT INTO `attendance` (`attendance_ID`, `course_ID`, `employee_ID`, `courseDate`) VALUES
(1, 1, 1, '2018-12-11'),
(2, 1, 2, '2018-12-12'),
(3, 2, 1, '2018-12-15'),
(4, 2, 2, '2018-12-12');

CREATE TABLE `courses` (
  `course_ID` INT(11),
  `course` VARCHAR(100),
  `courseDate` DATE,
  `department` VARCHAR(100)
);

INSERT INTO `courses` (`course_ID`, `course`, `courseDate`, `department`) VALUES
(1, 'Motivation', '2018-12-11', 'IT'),
(2, 'Hardware', '2018-12-22', 'HR');

CREATE TABLE `employee` (
  `employee_ID` INT(11),
  `name` VARCHAR(100),
  `surname` VARCHAR(100),
  `recordingDate` DATE,
  `offDay` INT(11),
  `workDay` INT(11),
  `department` VARCHAR(100),
  `status` VARCHAR(100)
);

INSERT INTO `employee` (`employee_ID`, `name`, `surname`, `recordingDate`, `offDay`, `workDay`, `department`, `status`) VALUES
(1, 'Georgie', 'Truax', '2018-12-04', 3, 20, 'IT', '1'),
(2, 'Ben', 'Killam', '2018-11-05', 14, 50, 'ART', '1'),
(3, 'Ronnie', 'Mehler', '2017-10-09', 32, 240, 'HR', '1'),
(4, 'Bertha', 'Raby', '2017-12-19', 22, 300, 'ART', '0');

CREATE TABLE `instructors` (
  `instructor_ID` INT(11),
  `name` VARCHAR(100),
  `surname` VARCHAR(100),
  `course_ID` INT(11)
);

INSERT INTO `instructors` (`instructor_ID`, `name`, `surname`, `course_ID`) VALUES
(1, 'Delena', 'Wigley', 1),
(2, 'Ken', 'Soluri', 2);

Yukarıdaki SQL komutlarını uyguladığınızda şu tabloları elde edersiniz:

attendance

attendance_ID course_ID employee_ID courseDate
1 1 1 2018-12-11
2 1 2 2018-12-12
3 2 1 2018-12-15
4 2 2 2018-12-12

courses

course_ID course courseDate department
1 Motivation 2018-12-11 IT
2 Hardware 2018-12-22 HR

employee

employee_ID name surname recordingDate offDay workDay department status
1 Georgie Truax 2018-12-04 3 20 IT 1
2 Ben Killam 2018-11-05 14 50 ART 1
3 Ronnie Mehler 2017-10-09 32 240 HR 1
4 Bertha Raby 2017-12-19 22 300 ART 0

instructors

instructor_ID name surname course_ID
1 Delena Wigley 1
2 Ken Soluri 2

INNER JOIN (İç Birleştirici)

Varsayılan seçenektir ve birebir ilişki için tercih edilir. İki veya daha fazla veri tablosunu belirtilen kolon veya kolonların eşitliğine göre ortak kolonlar üzerinden birleştirir. Kullanımında JOIN ifadesinin yanı sıra INNER JOIN şeklinde de tercih edilebilir. O halde, ilk işlemimizi gerçekleştirelim.

SELECT E.* FROM employee E INNER JOIN courses C ON E.department=C.department

Yukarıdaki JOIN kullanımı bize eğitimlere katılan çalışanları (employee) departman (department) ilişkisi üzerinden listeleyecektir. E.* bize tüm alanları sunacaktır. İlgili tanımlamayı belirli alanlarla sınırlandırmak için E.deparment gibi bir kullanım da tercih edebilirdik. Bu durumda sadece departman kolonu listelenecektir.

employee_ID name surname recordingDate offDay workDay department status
1 Georgie Truax 2018-12-04 3 20 IT 1
3 Ronnie Mehler 2017-10-09 32 240 HR 1

Şimdide bu işlemi kolon tanımlaması olmadan 3 tabloyu birleştirerek gerçekleştirelim.

SELECT * FROM courses C INNER JOIN employee E ON C.department=E.department INNER JOIN instructors I ON I.course_ID=C.course_ID
course_ID course courseDate department employee_ID name surname recordingDate
1 Motivation 2018-12-11 IT 1 Georgie Truax 2018-12-04
2 Hardware 2018-12-22 HR 3 Ronnie Mehler 2017-10-09
offDay workDay department status instructor_ID name surname
3 20 IT 1 1 Delena Wigley
32 240 HR 1 2 Ken Soluri

OUTER JOIN (Dış Birleştirici)

OUTER JOIN temelde INNER JOIN ile benzer şekilde ortak kolonlar üzerinden bağlantı kurar, ancak sonuç olarak tablolarda karşılığı olmayan satırları getirir. Bu sayede bir veri tablosunda olup bir diğerinde (veya diğerlerinde) olmayan kayıtları listeleyebiliriz. Kullanım aşamasında baskın olacak (temel olarak alınacak) tablo ayrıca LEFT ve RIGHT ifadeleriyle belirtilir ve belirtilen ikinci tabloda karşılığı olmayan satırlar NULL olarak gösterilir.

LEFT OUTER JOIN veya LEFT JOIN

Dış birleştiricilerden LEFT COIN solunda belirtilen tablodaki tüm satırları listeler ve sağ tarafta belirtilen tabloya ait kolonları ise NULL olarak döndürür. Hemen bir örnek gerçekleştirelim.

SELECT * FROM employee E LEFT JOIN courses C ON E.department=C.department

Bu SQL komutunu uyguladığımızda employee ve course kolonlarının birleştirilerek bize döndürüldüğünü ancak, eşleşme sağlanmayan alanların, yani herhangi bir kursa katılmayanların NULL değerini aldığını görebilirsiniz.

employee_ID name surname recordingDate offDay workDay department status
1 Georgie Truax 2018-12-04 3 20 IT 1
3 Ronnie Mehler 2017-10-09 32 240 HR 1
2 Ben Killam 2018-11-05 14 50 ART 1
4 Bertha Raby 2017-12-19 22 300 ART 0
course_ID course courseDate department
1 Motivation 2018-12-11 IT
2 Hardware 2018-12-22 HR
NULL NULL NULL NULL
NULL NULL NULL NULL

Aşağıda ayrıca 3 örnek daha iletiyorum. Sonuçları karşılaştırmak isterseniz bu konutları uygulayarak çıktıları değerlendirebilirsiniz.

SELECT * FROM employee E LEFT JOIN courses C ON E.department=C.department WHERE E.status=0 ORDER BY E.employee_ID ASC
SELECT * FROM courses C LEFT JOIN employee E ON C.department=E.department WHERE E.status=1 ORDER BY E.employee_ID ASC
SELECT * FROM employee E LEFT JOIN courses C ON E.department=C.department WHERE E.status=1 AND C.course IS NULL ORDER BY E.employee_ID ASC
RIGHT OUTER JOIN veya RIGHT JOIN

RIGHT JOIN, LEFT JOIN gibi yön belirtrerek sağında yer alan tablodaki tüm satırları listeler. Solunda yer alan tablo NULL olarak dönmektedir. Örneğimizi yukarıdaki örneklerden birini düzenleyerek oluşturacağım;

SELECT * FROM courses C RIGHT JOIN employee E ON C.department=E.department WHERE E.status=1 ORDER BY E.employee_ID ASC

Komutun uygulanmasının ardından herhangi bir kursa katılmayan çalışanın kurs bilgilerinin NULL olarak belirtildiğini görebilirsiniz.

FULL JOIN veya FULL OUTER JOIN

FULL JOIN, arasında belirtildiğitablolara ait (sağ ve sol) tüm satırları listeler ve bu tablolarda karşılığı olmayan satırları NULL olarak belirtir. FULL JOIN işlemi LEFT JOIN ve RIGHT JOIN işlemlerinin UNION ile birleştirilmesi şeklinde de uygulanabilir. Örneğin;

SELECT * FROM employee E LEFT JOIN attendance A ON E.employee_ID=A.employee_ID UNION SELECT * FROM employee E RIGHT JOIN courses C ON E.recordingDate=C.courseDate

CROSS JOIN (Çapraz Birleştirici)

Fazla kullanılmayan bir yöntemdir. Tablolar arasında yapılan birleştirmede seçilen kolonlar arasındaki tüm kombinasyonlar sonuç tablosu (result table) haline getirilir. Bu sonuç tablosundaki satır sayısı alanların kartezyen çarpımı (cartesian product / iki kümenin elemanlarının sırayla karşılaştırılması) kadardır. Örneğin, aşağıdaki işlem tüm kurslar için tüm eğitmenleri listeler.

SELECT * FROM courses C CROSS JOIN instructors I

SELF JOIN (Kendi Kendine Birleştirici)

Bir veri tablosunun kendisi ile birleştirilmesidir ve çok kullanılan bir yöntem değildir. Bir veri tablosundaki satırlar arasında referans ilişki olması durumunda o tablo için alias kullanılarak birleştirme işlemleri gerçekleştirilebilir. Bu şekilde tek bir tablo bağımsız tablolar gibi gösterilebilir.

UNION

FULL JOIN (FULL OUTER JOIN başlığı altında kısaca değindiğim UNION işleminden de ayrıca bahsetmek uygun olacaktır. UNION, birleştirme tiplerinin dışında, birden fazla tabloda sorgu gerçekleştirmek amacıyla kullanılan yöntemlerden biridir. Yukarıdaki örnekte birden fazla SELECT ifadesini tek bir sorgu olarak uygulamıştık, bu sayede tek sorgulama ile sonuç tablolar yaratılabilmektedir. UNION işleminde birleştirilmek istenen veri tablolarının belirlenen alanlar (kolonlar) aynı sayıda ve aynı veri tipinde olmalıdır. Alanların belirlenmesi işlemi SELECT ile sağlanır. Aynı satırdan birden fazla olsa dahi sonuç tablosunda oluşabilecek satırları göstermek için UNION ALL kullanılır.

SQL JOIN

Daha fazla örnek kullanım için MariaDB > Joining Tables with JOIN Clauses2 ve More Advanced Joins3 yazılarını inceleyebilirsiniz. Yukarıda, aşağıda yer alan görseli JOIN tiplerinin işlevlerine dair bir özet olarak değerlendirebilirsiniz. İlgili görselin düzenlenebilir AI (Adobe Illustrator) versiyonunu buradan indirebilirsiniz.

İleri Okumalar