ADIM ADIM SQL-2

Esin Çağla Kıral
10 min readMar 24, 2024

--

Merhabalar arkadaşlar, Bu blog başlatmış olduğum adım adım SQL serimin ikinci yazısı olacaktır. Bu yazıdan önce eğer SQL temeliniz yoksa “ Adım Adım SQL-1 “ yazımı okumanızı öneriyorum. Çünkü bu yazımda bahsedeceğim konuları iyi anlayabilmeniz için SQL de sorgu temelimizin olması gerekmektedir.

SQL öğrenirken almış olduğum notlarımı daha kapsamlı, detaylı ve bol örnekli hale getirerek edinmiş olduğum bilgilerle sizlere de aktarmak istedim. Bu yazımda oldukça kapsamlı bir konu olduğu için SQL ‘de İlişkili Tablolardan bahsetmek isterim sizlere. O halde hadi başlayalım :)

SQL İLE İLİŞKİLİ TABLOLAR

İlişkisel veritabanları, verileri mantıksal olarak birbirine bağlı tablolar halinde saklar. Bu tablolar arasındaki ilişkiler, verilerin daha düzenli, anlamlı ve verimli bir şekilde saklanmasına ve sorgulanmasına olanak tanıyor.

İlişkili tablo türleri arasında birebir (1:1), bire çok (1:N) ve çoktan çok’a (M:N) ilişkiler bulunur. Şimdi bu türleri ve nasıl çalıştıklarını örneklerle açıklayayım:

1. Bire Bir (1:1) İlişki

Bire bir ilişkide, bir tablodaki her kayıt diğer tablodaki yalnızca bir kayıtla eşleşir. Örneğin, bir Kullanıcılar tablosu ve her kullanıcının yalnızca bir KullanıcıDetay bilgisi olduğunu varsayalım.

Kullanıcılar Tablosu
KullanıcıDetay Tablosu

Her KullanıcıDetay girişi, Kullanıcılar tablosundaki bir KullanıcıID ile ilişkilidir. Bu, her kullanıcının yalnızca bir e-posta adresi olduğu anlamına gelir.

Mesela bir sorgu örneğiyle durumu biraz daha pekiştirelim. Kullanıcıların ve onların detay bilgilerinin birleştirilmiş bir listesini almak istersek bunu yapmak için INNER JOIN kullanmalıyız.

SELECT Kullanıcılar.KullanıcıID, Kullanıcılar.KullanıcıAdı, KullanıcıDetay.Eposta
FROM Kullanıcılar
INNER JOIN KullanıcıDetay ON Kullanıcılar.KullanıcıID = KullanıcıDetay.KullanıcıID;

Bu sorgu bizlere, her kullanıcı için kullanıcı adı ve e-posta adresini içeren bir liste döndürecektir.

Şimdi bu sorgunun nasıl çalıştığını detaylıca açıklayayım:

SELECT ifadesi sorgunun sonucunda hangi sütunların döndürüleceğini belirler. Burada Kullanıcılar.KullanıcıID, Kullanıcılar.KullanıcıAdı, ve KullanıcıDetay.Eposta sütunları seçilmiştir. Bu, her kullanıcının ID'si, adı ve e-posta adresi olmak üzere üç sütunu bizlere gösterecektir.

FROM ifadesi sorgunun hangi tablo üzerinde çalıştırılacağını belirtiyor. Bu örnekte, başlangıç tablosu olarak Kullanıcılar tablosu kullanılmıştır.

INNER JOIN ifadesiyle, Kullanıcılar tablosunu KullanıcıDetay tablosu ile birleştiriyoruz. Bu birleştirme işlemi, iki tablonun da KullanıcıID sütunları üzerinden gerçekleşmektedir. ON anahtar kelimesiyle belirtilen koşul (Kullanıcılar.KullanıcıID = KullanıcıDetay.KullanıcıID), hangi kayıtların birleştirileceğini tanımlamaktadır.

Peki sorgu nasıl çalışıyor?

  • INNER JOIN ifadesi, her iki tabloda da eşleşen kayıtları bulur. Yani, her iki tabloda da ortak olan KullanıcıID değerlerine sahip kayıtlar birleştirilir.
  • Sonuç olarak, her kullanıcının KullanıcıID, KullanıcıAdı ve ona ait Eposta bilgisini içeren bir sonuç seti elde edilir.
  • Eğer Kullanıcılar tablosundaki bir KullanıcıID, KullanıcıDetay tablosunda yoksa (veya tersi), bu kayıtlar sonuç setinde yer almaz. INNER JOIN yalnızca iki tabloda da eşleşen kayıtları döndürür, bu yüzden her iki tabloda da karşılığı olan kayıtlar sonuçta görünür.

2. Bire Çok (1:N) İlişki

Bire çok ilişkide, bir tablodaki bir kayıt diğer tablodaki birden çok kayıtla ilişkilendirilebilir. Örneğin, bir Yazarlar tablosu ve bir Kitaplar tablosu olduğunu düşünelim.

Yazarlar Tablosu
Kitaplar Tablosu

Bu durumda, Ahmet adlı yazarın iki kitabı varken, Elif adlı yazarın yalnızca bir kitabı vardır. Bu, bir Yazarlar kaydının Kitaplar tablosunda birden çok kayıtla ilişkilendirilebileceği anlamına gelir.

Mesela bir sorgu örneğiyle bire çok ilişki durumunu biraz daha pekiştirelim. Bir yazarın yazdığı kitapları listeleyelim. Bu örnekte, Ahmet’in (YazarID = 1) yazdığı kitapları sorgulayacağız:

SELECT Yazarlar.YazarAdı, Kitaplar.KitapAdı
FROM Yazarlar
INNER JOIN Kitaplar ON Yazarlar.YazarID = Kitaplar.YazarID
WHERE Yazarlar.YazarID = 1;

YazarID’si 1 olan yazarın (Ahmet) yazdığı kitapların listesini döndürmektedir. Şimdi bu sorgunun nasıl çalıştığını detaylıca açıklayayım:

FROM Yazarlar: Sorgu, Yazarlar tablosundan başlar. Bu, temel alınan tablodur ve buradan seçilecek veriler belirlenir.

INNER JOIN Kitaplar ON Yazarlar.YazarID = Kitaplar.YazarID: INNER JOIN kullanarak, Yazarlar tablosunu Kitaplar tablosuyla birleştirir. Bu birleştirme, her iki tabloda da bulunan YazarID sütunları üzerinden gerçekleştirilir. INNER JOIN kullanılmasının nedeni, sadece eşleşen kayıtların (yani, her iki tabloda da YazarID'ye sahip kayıtların) getirilmesi istenmesidir. Bu, bir yazarın yazdığı tüm kitapları bir liste olarak getirecektir.

SELECT Yazarlar.YazarAdı, Kitaplar.KitapAdı: Bu kısım, Yazarlar tablosundaki YazarAdı ve Kitaplar tablosundaki KitapAdı sütunlarını seçer. Bu şekilde, sonuç kümesi her bir kitap için yazar adını ve kitap adını içerecek şekilde oluşturulur.

WHERE Yazarlar.YazarID = 1: Sorgu, Yazarlar tablosundaki YazarID'si 1 olan yazarı filtreler. Bu, yalnızca belirli bir yazar (bu örnekte YazarID'si 1 olan) ve o yazarın kitapları hakkında bilgi almak istendiğinde kullanılır.

Sonuç olarak;

Veritabanından YazarID'si 1 olan yazarın adını ve bu yazarın yazdığı kitapların adlarını seçer. Eğer YazarID'si 1 olan yazar birden fazla kitap yazmışsa, bu kitapların her biri için bir satır olacak şekilde birden fazla satır döndürebilir. INNER JOIN kullanıldığı için, eğer YazarID'si 1 olan yazarın hiç kitabı yoksa, sorgu hiçbir sonuç döndürmez (çünkü INNER JOIN yalnızca eşleşen kayıtlarda çalışır ve eşleşme olmazsa sonuç döndürmez).

3. Çoktan Çoka (M:N) İlişki

Çoktan çoka ilişkilerde, bir tablodaki kayıtlar diğer tablodaki birden çok kayıtla ilişkilendirilebilir ve bu ilişki iki yönlüdür. Genellikle, bu tür ilişkileri yönetmek için üçüncü bir “arası” tablo kullanılır. Örneğin, Öğrenciler ve Dersler tabloları arasında bir ilişki düşünelim:

Öğrenciler Tablosu
Dersler Tablosu
ÖğrenciDers İlişkisi Tablosu

Bu durumda, Zeynep hem Matematik hem de Fizik derslerine kayıtlıyken, Mehmet yalnızca Fizik dersine kayıtlıdır. Bu, Öğrenciler ve Dersler arasındaki çoktan çoka ilişkiyi yöneten ÖğrenciDers İlişkisi tablosu ile sağlanır.

Mesela bir sorgu örneğiyle çoktan çoka ilişki durumunu biraz daha pekiştirelim. Öğrenciler ve onların kaydoldukları dersler arasındaki çoktan çoka ilişkiyi sorgulayalım. Örneğin, her öğrenci için kaydolduğu dersleri listeleyelim.

SELECT Öğrenciler.ÖğrenciAdı, Dersler.DersAdı
FROM Öğrenciler
INNER JOIN ÖğrenciDers İlişkisi ON Öğrenciler.ÖğrenciID = ÖğrenciDers İlişkisi.ÖğrenciID
INNER JOIN Dersler ON ÖğrenciDers İlişkisi.DersID = Dersler.DersID;

Bu sorgu, öğrencilerin her biri için kaydoldukları derslerin listesini döndürecektir. Çoktan çoka ilişkiler, bu ara tabloyla (ÖğrenciDers İlişkisi) yönetilir ve bu sorgu, ilişkili verileri bir araya getirmek için INNER JOIN kullanır.

Şimdi bu sorgunun nasıl çalıştığını detaylıca açıklayayım:

Bu sorgu, Öğrenciler, ÖğrenciDers İlişkisi (bu örnekte ara tablo olarak kullanılıyor) ve Dersler tablolarını kullanarak, öğrencilerin aldıkları derslerin listesini elde etmek için tasarlanmıştır. Bu sorgu, çoktan çoka bir ilişkiyi ele alır, çünkü bir öğrenci birden fazla ders alabilir ve bir ders de birden fazla öğrenci tarafından alınabilir.

FROM Öğrenciler: Sorgu, Öğrenciler tablosundan başlar. Bu, ilk referans noktasıdır ve sorgu bu tablodaki verilere dayanarak işlem yapar.

INNER JOIN ÖğrenciDers İlişkisi ON Öğrenciler.ÖğrenciID = ÖğrenciDers İlişkisi.ÖğrenciID: İlk olarak, Öğrenciler tablosu, ÖğrenciDers İlişkisi ara tablosu ile INNER JOIN kullanılarak birleştirilir. Bu birleştirme işlemi, her iki tabloda da ortak olan ÖğrenciID sütunları üzerinden gerçekleştirilir. Bu adım, her öğrencinin hangi dersleri aldığını belirlemek için gerekli olan öğrenci-ders ilişkisini kurar.

INNER JOIN Dersler ON ÖğrenciDers İlişkisi.DersID = Dersler.DersID: Ardından, ÖğrenciDers İlişkisi tablosu Dersler tablosu ile birleştirilir. Bu ikinci INNER JOIN işlemi, derslerin hangi dersler olduğunu anlamak için, ara tablodaki DersID ile Dersler tablosundaki DersID'yi eşleştirir.

SELECT Öğrenciler.ÖğrenciAdı, Dersler.DersAdı: Sorgu sonucunda, Öğrenciler tablosundan ÖğrenciAdı ve Dersler tablosundan DersAdı seçilir. Bu, sonuç kümesinin her satırında bir öğrenci adı ve bu öğrencinin aldığı bir ders adını içerecek şekilde düzenlenmesini sağlar.

Her bir ilişki türünü tablolar ve sorgu örnekleriyle ilk olarak detaylıca açıkladım. Sorguların nasıl bir mantıkla çalıştığını, tabloların ve verilerin birbirleriyle nasıl ilişki kurduklarını açıkladım. Şimdi ise daha detaylı sorgu örnekleri ve sonuç tabloları ile konuyu iyice pekiştirelim istiyorum.

Bire Bir İlişki Örneği: Kullanıcılar ve Kullanıcı Profilleri

Bu örnekte, her kullanıcının yalnızca bir profil bilgisi olduğunu düşünelim.

CREATE TABLE Kullanici (
KullaniciID INT PRIMARY KEY,
KullaniciAdi VARCHAR(50)
);

CREATE TABLE Profil (
ProfilID INT PRIMARY KEY,
KullaniciID INT,
DogumTarihi DATE,
Sehir VARCHAR(50),
FOREIGN KEY (KullaniciID) REFERENCES Kullanici(KullaniciID)
);

İlk olarak tablolarımızı oluşturuyoruz.

INSERT INTO Kullanici (KullaniciID, KullaniciAdi) VALUES (1, 'Ayşe');
INSERT INTO Kullanici (KullaniciID, KullaniciAdi) VALUES (2, 'Eren');

INSERT INTO Profil (ProfilID, KullaniciID, DogumTarihi, Sehir) VALUES (1, 1, '1990-05-01', 'İstanbul');
INSERT INTO Profil (ProfilID, KullaniciID, DogumTarihi, Sehir) VALUES (2, 2, '1992-08-15', 'Ankara');

Ardından Insert Into ifadesini kullanarak tablolarımıza verilerimizi ekliyoruz.

Şimdi ise bir kullanıcı ve onun profil bilgisini birleştirerek sorgulama yapalım:

SELECT K.KullaniciAdi, P.DogumTarihi, P.Sehir
FROM Kullanici K
JOIN Profil P ON K.KullaniciID = P.KullaniciID;
| KullaniciAdi | DogumTarihi | Sehir    |
|--------------|-------------|----------|
| Ayşe | 1990-05-01 | İstanbul |
| Eren | 1992-08-15 | Ankara |

Bu sonuç tablosu, her bir kullanıcının adı, doğum tarihi ve şehir bilgilerini içermektedir. İlk satırda “Ayşe” kullanıcısının profil bilgileri bulunmakta ve doğum tarihi 1990–05–01 ve şehri İstanbul olarak belirtilmektedir. İkinci satırda ise “Eren” kullanıcısının profil bilgileri bulunmakta ve doğum tarihi 1992–08–15 ve şehri Ankara olarak belirtilmektedir.

Bire Çok İlişki Örneği: Yazarlar ve Kitaplar

CREATE TABLE Yazar (
YazarID INT PRIMARY KEY,
YazarAdi VARCHAR(100)
);

CREATE TABLE Kitap (
KitapID INT PRIMARY KEY,
KitapAdi VARCHAR(100),
YazarID INT,
FOREIGN KEY (YazarID) REFERENCES Yazar(YazarID)
);

Yazar ve Kitap tablolarımızı oluşturduk.

INSERT INTO Yazar (YazarID, YazarAdi) VALUES (1, 'Orhan Pamuk');
INSERT INTO Yazar (YazarID, YazarAdi) VALUES (2, 'Elif Şafak');

INSERT INTO Kitap (KitapID, KitapAdi, YazarID) VALUES (1, 'Kara Kitap', 1);
INSERT INTO Kitap (KitapID, KitapAdi, YazarID) VALUES (2, 'Masumiyet Müzesi', 1);
INSERT INTO Kitap (KitapID, KitapAdi, YazarID) VALUES (3, 'Aşk', 2);

Tablolara veri ekledik. Şimdi de bir yazarın yazdığı kitapları sorgulayalım:

SELECT Y.YazarAdi, K.KitapAdi
FROM Yazar Y
JOIN Kitap K ON Y.YazarID = K.YazarID;
| YazarAdi     | KitapAdi         |
|--------------|------------------|
| Orhan Pamuk | Kara Kitap |
| Orhan Pamuk | Masumiyet Müzesi |
| Elif Şafak | Aşk |

Bu sonuç tablosu, her bir yazarın adı ve yazdığı kitapların adlarını içermektedir. İlk satırda “Orhan Pamuk” yazarının iki kitabı, “Kara Kitap” ve “Masumiyet Müzesi” bulunmaktadır. İkinci satırda “Elif Şafak” yazarının ise “Aşk” adında bir kitabı bulunmaktadır.

Çoktan Çoka İlişki Örneği: Öğrenciler ve Dersler

Bu örnekte, öğrencilerin birden fazla derse kayıt olabileceği ve bir dersin birden fazla öğrencisi olabileceğini düşünelim.

CREATE TABLE Ogrenci (
OgrenciID INT PRIMARY KEY,
OgrenciAdi VARCHAR(100)
);

CREATE TABLE Ders (
DersID INT PRIMARY KEY,
DersAdi VARCHAR(100)
);

CREATE TABLE OgrenciDers (
OgrenciID INT,
DersID INT,
FOREIGN KEY (OgrenciID) REFERENCES Ogrenci(OgrenciID),
FOREIGN KEY (DersID) REFERENCES Ders(DersID),
PRIMARY KEY (OgrenciID, DersID)
);

Ogrenci, Ders ve OgrenciDers tablolarımızı oluşturduk.

INSERT INTO Ogrenci (OgrenciID, OgrenciAdi) VALUES (1, 'Leyla');
INSERT INTO Ogrenci (OgrenciID, OgrenciAdi) VALUES (2, 'Mecnun');

INSERT INTO Ders (DersID, DersAdi) VALUES (1, 'Matematik');
INSERT INTO Ders (DersID, DersAdi) VALUES (2, 'Fizik');

INSERT INTO OgrenciDers (OgrenciID, DersID) VALUES (1, 1);
INSERT INTO OgrenciDers (OgrenciID, DersID) VALUES (1, 2);
INSERT INTO OgrenciDers (OgrenciID, DersID) VALUES (2, 1);

Tablolara verileri girdik. Şimdi ise bir dersi alan öğrencileri sorgulayalım:

SELECT D.DersAdi, O.OgrenciAdi
FROM OgrenciDers OD
JOIN Ogrenci O ON OD.OgrenciID = O.OgrenciID
JOIN Ders D ON OD.DersID = D.DersID;

Ortaya çıkacak olan sonuç tablosu ise aşağıdaki gibi olacaktır:

| DersAdi   | OgrenciAdi |
|-----------|------------|
| Matematik | Leyla |
| Fizik | Leyla |
| Matematik | Mecnun |

her bir dersin adı ile o dersi alan öğrencilerin adlarını içermektedir. İlk satırda “Matematik” dersini alan öğrenci “Leyla”, ikinci satırda yine “Fizik” dersini alan “Leyla” öğrencisi ve üçüncü satırda “Matematik” dersini alan “Mecnun” öğrencisi bulunmaktadır.

Bir başka örnek daha vereceğim ve konuya son örneğimle nokta koyacağım.

İlk olarak sorgu yapmadan önce tablolarımızı ve tablolar arası ilişki diyagramlarını göstermek itiyorum:

TBLNOTLAR Tablosu
TBLDERSLER Tablosu
TBLOGRENCILER Tablosu

Şimdi sorgumuzu yazalım:

Select NOTID,OGRAD + ' ' + OGRSOYAD AS 'AD SOYAD', DERSAD, SINAV1, SINAV2, SINAV3, ORTALAMA, DURUM From TBLNOTLAR
INNER JOIN TBLDERSLER
ON TBLNOTLAR.DERS = TBLDERSLER.DERSID
INNER JOIN TBLOGRENCILER
ON TBLNOTLAR.OGRENCI = TBLOGRENCILER.OGRID

Şimdi bu sorguda neler yapılmış haydi gelin detaylıca inceleyelim:

TBLNOTLAR adlı tablonun içeriğini sorgularken, bu tablodaki öğrenci ve ders bilgilerini kullanarak ilgili öğrencinin aldığı derslerin notlarını ve ders adlarını görüntülüyoruz.

FROM TBLNOTLAR: Sorgu, TBLNOTLAR tablosundan başlar. Bu tablo, öğrencilerin aldıkları derslere ve bu derslerde aldıkları notlara ilişkin bilgileri içerir.

INNER JOIN TBLDERSLER ON TBLNOTLAR.DERS = TBLDERSLER.DERSID: İlk INNER JOIN işlemi, TBLDERSLER tablosunu TBLNOTLAR tablosuyla birleştirir. Bu birleştirme, her bir notun TBLDERSLER tablosundaki ders bilgileri ile eşleştirilmesini sağlar. İki tablo arasındaki ilişki, DERSID alanının eşleşmesine dayanır.

INNER JOIN TBLOGRENCILER ON TBLNOTLAR.OGRENCI = TBLOGRENCILER.OGRID: İkinci INNER JOIN işlemi, TBLOGRENCILER tablosunu TBLNOTLAR tablosuyla birleştirir. Bu birleştirme, her bir notun TBLOGRENCILER tablosundaki öğrenci bilgileri ile eşleştirilmesini sağlar. İki tablo arasındaki ilişki, OGRID alanının eşleşmesine dayanır.

SELECT NOTID, OGRAD + ‘ ‘ + OGRSOYAD AS ‘AD SOYAD’, DERSAD, SINAV1, SINAV2, SINAV3, ORTALAMA, DURUM: Son olarak, istenen sütunlar seçilir ve gerekli düzenlemeler yapılır. Öğrencinin adı ve soyadı birleştirilerek AD SOYAD olarak yeni bir sütun oluşturulur. Bu sütun, öğrencinin adını ve soyadını tek bir sütun olarak gösterir. Ayrıca, ders adı, sınav notları, ortalama ve durum gibi bilgiler de seçilir.

Bu şekilde, TBLNOTLAR tablosundaki her bir not, hem ders bilgileri (TBLDERSLER tablosu) hem de öğrenci bilgileri (TBLOGRENCILER tablosu) ile eşleştirilir. Bu sayede, her notun hangi ders ve hangi öğrenciye ait olduğu görüntülenir. Sonuç tablosu da örnek olarak aşağıdaki gibi bir görüntü de olacaktır:

Sonuçlar Tablosu

Oldukça detaylı örnekler ve görsellerle SQL de Tablolar arası ilişki türlerini detaylıca anlatmaya çalıştım. Uzun bir konu olduğu için bu yazımı tamamen bu konuya ayırmak istedim. Unutmayalım ki SQL de tablolar arası ilişki kurmak çok önemlidir ve sıklıkla kullanılır. En çok kullanılan ilişki türü de Birden Çoka ilişki türüdür. Umarım detaylıca aktarabilmişimdir sizlere konuyu. Okuduğunuz için teşekkür ederim. Diğer yazılarımda görüşmek üzere…

İyi Kodlamalar :)

--

--