MySQL Join (LEFT, RIGHT, INNER, CROSS) Kullanımı ve Örnekleri
Merhaba arkadaşlar, bu yazımızda MySQL üzerinde LEFT JOIN, RIGHT JOIN, INNER JOIN ve CROSS JOIN kullanımını örneklerle birlikte inceleyeceğiz.
Join Nedir (Wiki: en) ?
Kısaca join; birbiriyle alakalı olan iki veya daha fazla tablolardan tek seferde veri çekme/filtreleme/sıralama işlemine yaramaktadır.
Join Kullanırken Yapılan En Büyük Hata Sütun Veri Tip ve Uzunluklarının Farklı Olmasıdır :
Evet, join yapılacak tabloların tablolar arası bağlantıyı kuran sütunların veri tipleri ve veri uzunlukları birbirinden farklıysa join kullanmak sorguyu çok uzatır ve performans kaybı yaşarsınız (yazımızın üçüncü sayfasından itibareb detaylar mevcut).
Örnek Senaryo :
Dört adet tablomuz olsun bunlardan ilki ürün listesi tutan urun tablosu, ikinci tablomuz ise ürünlerin detaylarını tutan urun_detay tablosu, üçüncü tablo firmamıza kayıtlı olan müşterileri tutacak olan musteri tablosu, son tablomuzda müşterilerimize satış yaptığımız ürünlerin kaydını tutan tablo satis olsun.
Firmam Veritabanı Sablonu:
Firmam Veritabanı SQL Kodu:
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL'; CREATE SCHEMA IF NOT EXISTS `firmam` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ; SHOW WARNINGS; USE `firmam` ; -- ----------------------------------------------------- -- Table `firmam`.`musteri` -- ----------------------------------------------------- DROP TABLE IF EXISTS `firmam`.`musteri` ; SHOW WARNINGS; CREATE TABLE IF NOT EXISTS `firmam`.`musteri` ( `musteri_id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'müşteri id (auto)' , `musteri_ad` VARCHAR(50) NOT NULL COMMENT 'müşterinin adı' , `musteri_soyad` VARCHAR(80) NOT NULL COMMENT 'müşterinin soyadı' , `musteri_telefon` INT UNSIGNED NOT NULL COMMENT 'müşterinin telefon numarası (alan kodu ile)' , `musteri_email` VARCHAR(100) NULL DEFAULT NULL COMMENT 'müşterinin email adresi' , `musteri_durum` ENUM('AKTIF','DEAKTIF') NOT NULL DEFAULT 'AKTIF' COMMENT 'müşteri durumu çalışılıyor yada çalışılmıyor' , PRIMARY KEY (`musteri_id`) ) ENGINE = InnoDB COMMENT = 'Müşterilerin bilgileri'; SHOW WARNINGS; CREATE INDEX `musteri_ad_idx` ON `firmam`.`musteri` (`musteri_ad` ASC) ; SHOW WARNINGS; CREATE INDEX `musteri_soyad_idx` ON `firmam`.`musteri` (`musteri_soyad` ASC) ; SHOW WARNINGS; CREATE INDEX `musteri_durum_idx` ON `firmam`.`musteri` (`musteri_durum` ASC) ; SHOW WARNINGS; -- ----------------------------------------------------- -- Table `firmam`.`musteri_detay` -- ----------------------------------------------------- DROP TABLE IF EXISTS `firmam`.`musteri_detay` ; SHOW WARNINGS; CREATE TABLE IF NOT EXISTS `firmam`.`musteri_detay` ( `musteri_id` INT UNSIGNED NOT NULL COMMENT 'müşteri id (fk)' , `musteri_detay_ulke` CHAR(2) NOT NULL COMMENT 'müşteri ülke kodu' , `musteri_detay_sehir` VARCHAR(45) NOT NULL COMMENT 'müşteri şehir adı' , `musteri_detay_ilce` VARCHAR(45) NULL DEFAULT NULL COMMENT 'müşteri ilçe adı' , `musteri_detay_postakodu` VARCHAR(45) NULL DEFAULT NULL COMMENT 'müşteri postakodu' , `musteri_detay_adres` VARCHAR(45) NULL DEFAULT NULL COMMENT 'müşteri açık adres' , `musteri_detay_website` VARCHAR(45) NULL DEFAULT NULL COMMENT 'müşteri website adresi' , PRIMARY KEY (`musteri_id`) , CONSTRAINT `musteri_detay_musteri_id_fkey` FOREIGN KEY (`musteri_id` ) REFERENCES `firmam`.`musteri` (`musteri_id` ) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE = InnoDB COMMENT = 'Müşteri detay bilgileri'; SHOW WARNINGS; CREATE INDEX `musteri_detay_musteri_id_fkey` ON `firmam`.`musteri_detay` (`musteri_id` ASC) ; SHOW WARNINGS; CREATE INDEX `musteri_detay_ulke_idx` ON `firmam`.`musteri_detay` (`musteri_detay_ulke` ASC) ; SHOW WARNINGS; CREATE INDEX `musteri_detay_website_idx` ON `firmam`.`musteri_detay` (`musteri_detay_website` ASC) ; SHOW WARNINGS; -- ----------------------------------------------------- -- Table `firmam`.`urun` -- ----------------------------------------------------- DROP TABLE IF EXISTS `firmam`.`urun` ; SHOW WARNINGS; CREATE TABLE IF NOT EXISTS `firmam`.`urun` ( `urun_id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ürün id (auto)' , `urun_adi` VARCHAR(80) NOT NULL COMMENT 'ürün adı' , `urun_marka` VARCHAR(45) NOT NULL COMMENT 'ürün markası' , `urun_model` VARCHAR(45) NOT NULL COMMENT 'ürün modeli' , `urun_uretim` DATE NOT NULL COMMENT 'ürün üretim tarihi' , PRIMARY KEY (`urun_id`) ) ENGINE = InnoDB COMMENT = 'Ürün tablosu'; SHOW WARNINGS; CREATE INDEX `urun_adi_idx` ON `firmam`.`urun` (`urun_adi` ASC) ; SHOW WARNINGS; CREATE INDEX `urun_marka_idx` ON `firmam`.`urun` (`urun_marka` ASC) ; SHOW WARNINGS; CREATE INDEX `urun_uretim_idx` ON `firmam`.`urun` (`urun_uretim` ASC) ; SHOW WARNINGS; -- ----------------------------------------------------- -- Table `firmam`.`satis` -- ----------------------------------------------------- DROP TABLE IF EXISTS `firmam`.`satis` ; SHOW WARNINGS; CREATE TABLE IF NOT EXISTS `firmam`.`satis` ( `satis_id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'satış id (auto)' , `urun_id` INT UNSIGNED NOT NULL COMMENT 'satılan ürün id (fk)' , `musteri_id` INT UNSIGNED NOT NULL COMMENT 'ürün satılan müşteri id (fk)' , `satis_birim` FLOAT UNSIGNED NOT NULL COMMENT 'birim fiyatı' , `satis_miktar` INT UNSIGNED NOT NULL COMMENT 'satış miktarı (adet)' , `satis_tutar` FLOAT UNSIGNED NOT NULL COMMENT 'toplam tutar (TL)' , `satis_tarih` DATETIME NOT NULL COMMENT 'satış tarihi' , PRIMARY KEY (`satis_id`) , CONSTRAINT `satis_urun_id_fkey` FOREIGN KEY (`urun_id` ) REFERENCES `firmam`.`urun` (`urun_id` ) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `satis_musteri_id_fkey` FOREIGN KEY (`musteri_id` ) REFERENCES `firmam`.`musteri` (`musteri_id` ) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE = InnoDB COMMENT = 'Ürün satış tablosu'; SHOW WARNINGS; CREATE INDEX `satis_urun_id_fkey` ON `firmam`.`satis` (`urun_id` ASC) ; SHOW WARNINGS; CREATE INDEX `satis_musteri_id_fkey` ON `firmam`.`satis` (`musteri_id` ASC) ; SHOW WARNINGS; CREATE INDEX `satis_miktar_idx` ON `firmam`.`satis` (`satis_miktar` ASC) ; SHOW WARNINGS; CREATE INDEX `satis__tarih_idx` ON `firmam`.`satis` (`satis_tarih` ASC) ; SHOW WARNINGS; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
Firmam Veritabanı Kaynak Kodları:
Veritabanı tasarımında MySQL Workbench kullandık. Kaynak dosyayı buradan indirebilirsiniz.
Firmam Veritabanı Müşteri (musteri) Tablosu Örnek Kayıtlar:
INSERT INTO `firmam`.`musteri` ( `musteri_id` , `musteri_ad` , `musteri_soyad` , `musteri_telefon` , `musteri_email` , `musteri_durum` ) VALUES ( NULL , 'Ahmet', 'AY', '02125555555', '[email protected]', 'AKTIF' ), ( NULL , 'Mehmet', 'YILDIZ', '02125555556', '[email protected]', 'AKTIF' ), ( NULL , 'Ali', 'KİBAR', '02125555557', '[email protected]', 'AKTIF' ), ( NULL , 'Mustafa', 'KIRIMLI', '05555555555', '[email protected]', 'AKTIF' ), ( NULL , 'John', 'DOE', '02127777777', '[email protected]', 'AKTIF' ), ( NULL , 'Jane', 'DOE', '02128888888', '[email protected]', 'DEAKTIF' )
Firmam Veritabanı Müşteri Detay (musteri_detay) Tablosu Örnek Kayıtlar:
INSERT INTO `musteri_detay` ( `musteri_id` , `musteri_detay_ulke` , `musteri_detay_sehir` , `musteri_detay_ilce` , `musteri_detay_postakodu` , `musteri_detay_adres` , `musteri_detay_website` ) VALUES ( 1, 'US', 'New York', NULL , NULL , NULL , NULL ) , ( 4, 'TR', 'İstanbul', NULL , NULL , NULL , 'http://mustafakirimli.com' )
Firmam Veritabanı Ürün (urun) Tablosu Örnek Kayıtlar:
INSERT INTO `firmam`.`urun` ( `urun_id` , `urun_adi` , `urun_marka` , `urun_model` , `urun_uretim` ) VALUES ( NULL , 'Asus Notebook B43 4GB', 'Asus', 'B43', '2010-04-01' ), ( NULL , 'Asus Notebook N51V 4GB', 'Asus', 'N51V', '2009-12-01' );
Firmam Veritabanı Satış (satis) Tablosu Örnek Kayıtlar:
INSERT INTO `firmam`.`satis` ( `satis_id` , `urun_id` , `musteri_id` , `satis_birim` , `satis_miktar` , `satis_tutar` , `satis_tarih` ) VALUES ( NULL , '1', '5', '100', '40', '4000', '2010-12-01 10:00:00' ), ( NULL , '1', '5', '150', '10', '1500', '2010-12-02 10:00:00' ), ( NULL , '1', '4', '170', '10', '1700', '2010-12-02 11:00:00' ), ( NULL , '1', '5', '140', '10', '1400', '2010-12-02 12:00:00' ), ( NULL , '1', '6', '100', '10', '1000', '2010-12-03 10:00:00' ), ( NULL , '2', '5', '100', '30', '3000', '2010-12-03 12:00:00' ), ( NULL , '2', '5', '100', '20', '2000', '2010-12-03 13:00:00' ), ( NULL , '2', '2', '180', '10', '1000', '2010-12-03 14:00:00' ), ( NULL , '2', '2', '100', '10', '1000', '2010-12-03 15:00:00' ), ( NULL , '2', '3', '100', '30', '3000', '2010-12-03 16:41:00' ), ( NULL , '2', '3', '120', '20', '2400', '2010-12-03 16:58:00' ), ( NULL , '2', '4', '100', '30', '3000', '2010-12-03 17:15:00' ), ( NULL , '2', '1', '100', '10', '1000', '2010-12-03 17:30:00' );
Firmam Veritabanındaki Veriler
Müşteri (musteri) Tablosu:
SELECT * FROM `firmam`.`musteri`; +------------+------------+---------------+-----------------+-------------------------+---------------+ | musteri_id | musteri_ad | musteri_soyad | musteri_telefon | musteri_email | musteri_durum | +------------+------------+---------------+-----------------+-------------------------+---------------+ | 1 | Ahmet | AY | 2125555555 | [email protected] | AKTIF | | 2 | Mehmet | YILDIZ | 2125555556 | [email protected] | AKTIF | | 3 | Ali | KİBAR | 2125555557 | [email protected] | AKTIF | | 4 | Mustafa | KIRIMLI | 4294967295 | [email protected] | AKTIF | | 5 | John | DOE | 2127777777 | [email protected] | AKTIF | | 6 | Jane | DOE | 2128888888 | [email protected] | DEAKTIF | +------------+------------+---------------+-----------------+-------------------------+---------------+ 6 rows in set
Müşteri Detay (musteri_detay) Tablosu:
SELECT * FROM `firmam`.`musteri_detay`; +------------+--------------------+---------------------+--------------------+-------------------------+---------------------+---------------------------+ | musteri_id | musteri_detay_ulke | musteri_detay_sehir | musteri_detay_ilce | musteri_detay_postakodu | musteri_detay_adres | musteri_detay_website | +------------+--------------------+---------------------+--------------------+-------------------------+---------------------+---------------------------+ | 1 | US | New York | NULL | NULL | NULL | NULL | | 4 | TR | İstanbul | NULL | NULL | NULL | http://mustafakirimli.com | +------------+--------------------+---------------------+--------------------+-------------------------+---------------------+---------------------------+ 2 rows in set
Ürün (urun) Tablosu:
SELECT * FROM `firmam`.`urun`; +---------+------------------------+------------+------------+-------------+ | urun_id | urun_adi | urun_marka | urun_model | urun_uretim | +---------+------------------------+------------+------------+-------------+ | 1 | Asus Notebook B43 4GB | Asus | B43 | 2010-04-01 | | 2 | Asus Notebook N51V 4GB | Asus | N51V | 2009-12-01 | +---------+------------------------+------------+------------+-------------+ 2 rows in set
Satış (satis) Tablosu:
SELECT * FROM `firmam`.`satis`; +----------+---------+------------+-------------+--------------+-------------+---------------------+ | satis_id | urun_id | musteri_id | satis_birim | satis_miktar | satis_tutar | satis_tarih | +----------+---------+------------+-------------+--------------+-------------+---------------------+ | 1 | 1 | 5 | 100 | 40 | 4000 | 2010-12-01 10:00:00 | | 2 | 1 | 5 | 100 | 10 | 1000 | 2010-12-02 10:00:00 | | 3 | 1 | 5 | 100 | 40 | 4000 | 2010-12-01 10:00:00 | | 4 | 1 | 5 | 150 | 10 | 1500 | 2010-12-02 10:00:00 | | 5 | 1 | 4 | 170 | 10 | 1700 | 2010-12-02 11:00:00 | | 6 | 1 | 5 | 140 | 10 | 1400 | 2010-12-02 12:00:00 | | 7 | 1 | 6 | 100 | 10 | 1000 | 2010-12-03 10:00:00 | | 8 | 2 | 5 | 100 | 30 | 3000 | 2010-12-03 12:00:00 | | 9 | 2 | 5 | 100 | 20 | 2000 | 2010-12-03 13:00:00 | | 10 | 2 | 2 | 180 | 10 | 1000 | 2010-12-03 14:00:00 | | 11 | 2 | 2 | 100 | 10 | 1000 | 2010-12-03 15:00:00 | | 12 | 2 | 3 | 100 | 30 | 3000 | 2010-12-03 16:41:00 | | 13 | 2 | 3 | 120 | 20 | 2400 | 2010-12-03 16:58:00 | | 14 | 2 | 4 | 100 | 30 | 3000 | 2010-12-03 17:15:00 | | 15 | 2 | 1 | 100 | 10 | 1000 | 2010-12-03 17:30:00 | +----------+---------+------------+-------------+--------------+-------------+---------------------+ 15 rows in set
INNER JOIN Kullanımı:
İlk olarak en yaygın kullanılan JOIN tipi olan INNER JOIN ‘i inceleyeceğiz. INNER JOIN seçtiğiniz tablolarda birebir eşleşen kayıtları getirir. Örneğin musteri ve musteri_detay tablolarını inceleyecek olursanız 6 adet müşteri kaydımız ve 2 adet müşteri detay kaydımız bulunuyor. Biz bu tablolar için INNER JOIN kullanırsak bize sadece 2 satır kayıt dönecektir. Çünkü her iki tabloda kaydı bulunan musteri sadece 2 tanedir.
Örnek INNER JOIN Sorgusu :
SELECT m.*, md.musteri_detay_website FROM firmam.musteri AS m INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
Örnek INNER JOIN Sorgu Sonucu :
+------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | musteri_id | musteri_ad | musteri_soyad | musteri_telefon | musteri_email | musteri_durum | musteri_detay_website | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | 1 | Ahmet | AY | 2125555555 | [email protected] | AKTIF | NULL | | 4 | Mustafa | KIRIMLI | 4294967295 | [email protected] | AKTIF | http://mustafakirimli.com | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ 2 rows in set (0.00 sec)
Yukarıdaki sorgumuzda sonuç sütunlarının ekrana sığması açısından musteri tablosundaki tüm sütunları, musteri_detay tablosundaki musteri_detay_website sütununu seçtik. Siz isterseniz “*” kullanarak hepsini seçebilirsiniz. Zaten büyük tablololarda performans kazanmak için gerekmeyen sütunların seçilmemesi önerilir.
INNER JOIN kullanarak bir örnek daha yapmış olalım. Bizden İstanbul ‘da olan müşterilerin adı, soyadı ve telefon bilgileri isteniyor olsun. Sorgumuz aşağıdaki gibi olacaktır.
SELECT m.musteri_ad, m.musteri_soyad, m.musteri_telefon FROM firmam.musteri AS m INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id WHERE md.musteri_detay_sehir = 'İstanbul'
Sorgunun sonucu aşağıdaki gibidir:
+------------+---------------+-----------------+ | musteri_ad | musteri_soyad | musteri_telefon | +------------+---------------+-----------------+ | Mustafa | KIRIMLI | 4294967295 | +------------+---------------+-----------------+ 1 row in set (0.00 sec)
Bir başka INNER JOIN örneği
Şimdide hem 3 tabloyu JOIN yapmayı inceleyelim hemde sorgumuzu biraz daha karşamık hale getirelim. Bizden kısaca kime, hangi ürünü, kaç adet, toplam ne kadara? sorularının SQL sonuçlarını istiyor olsunlar.
Burada yapacağımız şey satış tablosundan yola çıkarak müşteri bilgilerini almak için müşteri tablosunu satış tablosuna JOIN yapmak ve daha sonra ürün bilgilerini almak için ürün tablosunu satış tablosuna JOIN yapmak olacak.
SELECT m.musteri_ad, m.musteri_soyad, m.musteri_telefon, u.urun_adi, s.satis_miktar, s.satis_tutar FROM firmam.satis AS s INNER JOIN firmam.musteri AS m ON s.musteri_id = m.musteri_id INNER JOIN firmam.urun AS u ON s.urun_id = u.urun_id WHERE 1 ORDER BY m.musteri_id
Sorgu Sonucu :
+------------+---------------+-----------------+------------------------+--------------+-------------+ | musteri_ad | musteri_soyad | musteri_telefon | urun_adi | satis_miktar | satis_tutar | +------------+---------------+-----------------+------------------------+--------------+-------------+ | Ahmet | AY | 2125555555 | Asus Notebook N51V 4GB | 10 | 1000 | | Mehmet | YILDIZ | 2125555556 | Asus Notebook N51V 4GB | 10 | 1000 | | Mehmet | YILDIZ | 2125555556 | Asus Notebook N51V 4GB | 10 | 1000 | | Ali | KİBAR | 2125555557 | Asus Notebook N51V 4GB | 30 | 3000 | | Ali | KİBAR | 2125555557 | Asus Notebook N51V 4GB | 20 | 2400 | | Mustafa | KIRIMLI | 4294967295 | Asus Notebook B43 4GB | 10 | 1700 | | Mustafa | KIRIMLI | 4294967295 | Asus Notebook N51V 4GB | 30 | 3000 | | John | DOE | 2127777777 | Asus Notebook B43 4GB | 10 | 1400 | | John | DOE | 2127777777 | Asus Notebook N51V 4GB | 30 | 3000 | | John | DOE | 2127777777 | Asus Notebook B43 4GB | 40 | 4000 | | John | DOE | 2127777777 | Asus Notebook B43 4GB | 40 | 4000 | | John | DOE | 2127777777 | Asus Notebook N51V 4GB | 20 | 2000 | | John | DOE | 2127777777 | Asus Notebook B43 4GB | 10 | 1000 | | John | DOE | 2127777777 | Asus Notebook B43 4GB | 10 | 1500 | | Jane | DOE | 2128888888 | Asus Notebook B43 4GB | 10 | 1000 | +------------+---------------+-----------------+------------------------+--------------+-------------+ 15 rows in set (0.00 sec)
JOIN İle USING Kullanımı
Tüm JOIN tiplerinde ON clause yerine USING kullanılabilir. USING kullanmanın kısıtlamaları ise her iki tabloda da aynı ada sahip sütunların olması gerekliliğidir. İlk sorgumuzu USING kullanarak yeniden yazalım.
SELECT m.*, md.musteri_detay_website FROM firmam.musteri AS m INNER JOIN firmam.musteri_detay AS md USING(musteri_id)
Sorgu sonucu değişmeyeceği için çıktıyı buraya yazmadık.
JOIN Kullanırken “#1052 – Column ‘column_name’ in where clause is ambiguous” Hatası Almak
Örneğin sizden musteri_id si 1 olan musterinin tüm bilgilerini isterlerse aşağıdaki sorguyu yazarak sonuca ulaşmak isteyebilirsiniz. Ancak MySQL size “#1052 – Column ‘musteri_id’ in where clause is ambiguous” hatası döner. Bunun sebebi seçilen sütunların arasında aynı adı taşıyanlar olması ve sizin buna filtre uygulamaya çalışmanızdır. Örneğin aşağıdaki örnekte musteri_id si 1 olan kaydı getir dedik ancak musteri_id her iki tabloda da bulunduğundan MySQL ‘in biraz kafası karışır. Bu örnek tam yerinde olmamakla birlikte zaten bu sorguyu doğru çalıştırması asıl bizim başımızı ağrıtabilir. Bu sebeple birden fazla tablo kullanıyorsak SELECT, WHERE, GROUP BY, ORDER vb. bölümlerinde mutlaka tablo adı yada tablo aliaslarını (lakaplarını) bebelirtmek yarayımıza olacaktır.
Yanlış Kullanım :
SELECT * FROM firmam.musteri AS m INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id WHERE musteri_id = 1
Sorgumuzun doğru yazılmış biçimi aşağıdadır:
SELECT * FROM firmam.musteri AS m INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id WHERE m.musteri_id = 1
LEFT JOIN Kullanımı
LEFT JOIN, seçilen tablolardan soldaki bulunan tablonun tamamını alır ve sağdaki tablodan da varsa eşleşen kayıtları alır yoksa NULL ile doldurulmuş kayıtlar döner.
Bir örnekle pekiştirmeye çalışalım. Veritabanında kayıtlı müsterileri ve varsa müşteri detay bilgilerini almamız gerektiğini varsayalım. INNER JOIN ‘i hatırlayacak olursak her iki tabloda da musterinin bulunması zorunluluğu vardı ama LEFT JOIN kullandığınızda bu zorunluluk ortadan kalkıyor.
Müşteri ve Varsa Müşteri Detay Bilgilerini Alan SQL :
SELECT m.*, md.musteri_detay_website FROM firmam.musteri AS m LEFT JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id WHERE 1
Sorgu Sonucu:
+------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | musteri_id | musteri_ad | musteri_soyad | musteri_telefon | musteri_email | musteri_durum | musteri_detay_website | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | 1 | Ahmet | AY | 2125555555 | [email protected] | AKTIF | NULL | | 2 | Mehmet | YILDIZ | 2125555556 | [email protected] | AKTIF | NULL | | 3 | Ali | KİBAR | 2125555557 | [email protected] | AKTIF | NULL | | 4 | Mustafa | KIRIMLI | 4294967295 | [email protected] | AKTIF | http://mustafakirimli.com | | 5 | John | DOE | 2127777777 | [email protected] | AKTIF | NULL | | 6 | Jane | DOE | 2128888888 | [email protected] | DEAKTIF | NULL | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ 6 rows in set (0.00 sec)
Sorgu sonucunu bir önceki sayfada bulunan INNER JOIN örneğinde ki sonuç ile karşılaştırdığımızda 4 adet fazla kayıt döndüğünü görürüz. LEFT JOIN kullandığımızda soldaki tabloda (musteri tablosu) bulunan kayıtların tamamını alır (6 adet), sağdaki tablonun ise (musteri_detay) eşleşen kayıtlar (musteri_id ile) varsa birleştirir yoksa NULL basarak satırı doldurur.
Soldaki tablo kendisinden önce yazılan tablo anlamına gelir. Yani musteri AS m LEFT JOIN musteri_detay AS md sorgusunda musteri tablosu musteri_detay tablosundan önce yazıldığından soldaki tablo olarak anılır. Sorguyu musteri _detayAS md LEFT JOIN musteri AS m şeklinde yazarsak soldaki tablo bildiğiniz gibi musteri_detay olacaktır.
1:n Relationships (birden çoğa bağlantı) Durumunda LEFT JOIN Davranışı :
Birden çoğa bağlantılı tabloları LEFT JOIN ile birleştirdiğimizde n tarafındaki tablodaki varlık kadar satır tekrarı yapılacaktır. Bunun anlamı müşteriler tablomuz ile satış tablomuzu LEFT JOIN ile birleştirirsek müşteriye yapılan satış sayısı kadar müşteri kaydı satır tekrarlaması yapılacaktır. Biraz daha açacak olursak müşteri tablomuzda aynı musteri_id ‘si ile sadece bir adet kayıt bulunabilir. Ancak bir müşteriye birden fazla satış yapabileceğimiz için satış tablosunda birden fazla musteri_id ye sahip kayıt bulunabilir.
Bir örnekle inceleyelim:
SELECT m.musteri_id , m.musteri_ad , m.musteri_soyad , s.satis_id, s.musteri_id , s.satis_tutar FROM firmam.musteri AS m LEFT JOIN firmam.satis AS s ON m.musteri_id = s.musteri_id WHERE 1
Sorgu Sonucu :
+------------+------------+---------------+----------+------------+-------------+ | musteri_id | musteri_ad | musteri_soyad | satis_id | musteri_id | satis_tutar | +------------+------------+---------------+----------+------------+-------------+ | 1 | Ahmet | AY | 15 | 1 | 1000 | | 2 | Mehmet | YILDIZ | 10 | 2 | 1000 | | 2 | Mehmet | YILDIZ | 11 | 2 | 1000 | | 3 | Ali | KİBAR | 12 | 3 | 3000 | | 3 | Ali | KİBAR | 13 | 3 | 2400 | | 4 | Mustafa | KIRIMLI | 5 | 4 | 1700 | | 4 | Mustafa | KIRIMLI | 14 | 4 | 3000 | | 5 | John | DOE | 1 | 5 | 4000 | | 5 | John | DOE | 2 | 5 | 1000 | | 5 | John | DOE | 3 | 5 | 4000 | | 5 | John | DOE | 4 | 5 | 1500 | | 5 | John | DOE | 6 | 5 | 1400 | | 5 | John | DOE | 8 | 5 | 3000 | | 5 | John | DOE | 9 | 5 | 2000 | | 6 | Jane | DOE | 7 | 6 | 1000 | +------------+------------+---------------+----------+------------+-------------+ 15 rows in set
Yukarıdaki sorgu sonucunu inceleyecek olursak müşteri bilgilerinin tekrarladığını göreceğiz. Bizim 6 adet müşterimiz olmasına rağmen 15 adet sorgu sonucu dönmüş durumda. Önemli bir hatırlatma: buradaki sorgu sonucu sayısı sadece satış tablosunun kayıt sayısına eşit değildir. Bu tip birleştirmelerde sorgu sayısı sonucu 1 tarafındaki (musteri) tablo ile n tarafındaki (satış) tablosu arasındaki ortak kayıtlar + 1 tarafındaki (müşteri) tablodaki ortak olmayan kayıtlar şeklindedir. Hesaplayacak olursak, satış tablosundaki kayıtların hepsini müşteri tablosuna ortak (musteri_id sinin karşılığı musteri tablosunda var) olduğunu için tamamı (15 adet) + musteri tablosunda olup satis tablosunda olmayan kayıtlar (0 adet) yani toplamda 15+0 = 15 satır.
Gelişmiş LEFT JOIN Kullanımı :
Şimdi biraz basit LEFT JOIN birleştirmelerini bir adım daha ileriye taşımak için küçük bir örnek daha yapalım. Klasik LEFT JOIN birleştirmesi aslında nette onlarca ve hatta yüzlerce bulabileceğiniz bir örnektir. Ancak detaylı bir sorgu istediğimizde (ilk zamanlarda bizimde yaşadığımız) örnek bulma konusunda zaman zaman güçlük çekilebiliyor.
Örneğimizde kayıtlı ürünlerin tam listesi ile birlikte varsa 01-12-2010 (2010-12-01 Y-m-d) tarihinde yapılan satışların bilgileri isteniyor olsun.
SELECT u.* , s.satis_miktar FROM firmam.urun AS u LEFT JOIN firmam.satis AS s ON u.urun_id = s.urun_id AND s.satis_tarih BETWEEN '2010-12-01 00:00:00' AND '2010-12-01 23:59:59' WHERE 1
Sorgu Sonucu :
+---------+------------------------+------------+------------+-------------+--------------+ | urun_id | urun_adi | urun_marka | urun_model | urun_uretim | satis_miktar | +---------+------------------------+------------+------------+-------------+--------------+ | 1 | Asus Notebook B43 4GB | Asus | B43 | 2010-04-01 | 40 | | 1 | Asus Notebook B43 4GB | Asus | B43 | 2010-04-01 | 40 | | 2 | Asus Notebook N51V 4GB | Asus | N51V | 2009-12-01 | NULL | +---------+------------------------+------------+------------+-------------+--------------+ 3 rows in set (0.00 sec)
Sorgu sonucunda görüldüğü gibi 3 adet kayıt döndü. Sorguyu inceleyecek olursak ON clause kısmından sonra AND diyerek JOIN işlemine devam ettik. MySQL burada sağdaki tablodan sadece belirttiğimiz tarih aralığına uyan kayıtları seçti ve soldaki tabloya normal LEFT JOIN işlemiyle birleştirme yaptı. Eğer tarih aralığını WHERE kısmında verirseniz dönen satır sayısı 2 olacaktır. Bu sorgu senaryosu tam olarak gerçeği yansıtmıyor gibi görülebilir ancak bazen çok gerekli bir yöntem oluyor.
Sorgudan anlaşılması gereken kısım LEFT JOIN yapılırken sağdaki tabloda kayıtların olması yada olmaması durumunun ON clause bölümüne yazılırsa devam etmesidir. WHERE clause kısmına geçtiğinizde tablo çoktan birleştirilmiştir ve siz birleştirilmiş tablo üzerinde kesin filtreleme yapıyor olursunuz. Bu sebeple yaptığınız filtre direkt olarak satırları eleyecektir.
Yukarıdaki örneğin biraz daha düzgün hali (gerçek bir rapor formatına en yakın) aşağıdaki gibidir.
SELECT u.* , SUM(s.satis_miktar) AS toplam_miktar FROM firmam.urun AS u LEFT JOIN firmam.satis AS s ON u.urun_id = s.urun_id AND s.satis_tarih BETWEEN '2010-12-01 00:00:00' AND '2010-12-01 23:59:59' WHERE 1 GROUP BY u.urun_id
Sorgu Sonucu :
+---------+------------------------+------------+------------+-------------+---------------+ | urun_id | urun_adi | urun_marka | urun_model | urun_uretim | toplam_miktar | +---------+------------------------+------------+------------+-------------+---------------+ | 1 | Asus Notebook B43 4GB | Asus | B43 | 2010-04-01 | 80 | | 2 | Asus Notebook N51V 4GB | Asus | N51V | 2009-12-01 | NULL | +---------+------------------------+------------+------------+-------------+---------------+ 2 rows in set (0.00 sec)
RIGHT JOIN Kullanımı
MySQL RIGHT JOIN, LEFT JOIN işleminin tersini yapar. Yani seçilen tablolardan sağdaki bulunan tablonun tamamını alır ve soldaki tablodan da varsa eşleşen kayıtları alır yoksa NULL ile doldurulmuş kayıtlar döner.
İlk LEFT JOIN Örneğinin RIGHT JOIN ile Yazımı :
SELECT m.*, md.musteri_detay_website FROM firmam.musteri AS m RIGHT JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id WHERE 1
Sorgu Sonucu :
+------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | musteri_id | musteri_ad | musteri_soyad | musteri_telefon | musteri_email | musteri_durum | musteri_detay_website | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | 1 | Ahmet | AY | 2125555555 | [email protected] | AKTIF | NULL | | 4 | Mustafa | KIRIMLI | 4294967295 | [email protected] | AKTIF | http://mustafakirimli.com | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ 2 rows in set (0.01 sec)
Yukarıdaki örnekte 2 adet sorgu sonucu döndü. Bunun sebebi RIGHT JOIN kullandığınızda tabloların sağa birleştirilmesi. Sağdaki tablodaki (musteri_detay tablosu) tüm verileri (2 adet) alır ve sağdaki tablo ile soldaki (musteri) tablo arasındaki ortak veriler varsa alır yoksa NULL doldurur. Kaydı olmayan müşterinin detayı olamayacağı için soldaki tablo NULL ile doldurulmuş gelmez (tablodaki NULL olabilecek kolonlar hariç). Bu SQL başka bir deyişle müşteri detay bilgisi olan kayıtları getir demektir.
RIGHT JOIN ‘i LEFT JOIN gibi Kullanmak :
RIGHT JOIN ‘i LEFT JOIN ile karşılaştırmak istiyorsanız sorgunuzdaki tabloların yazım sırasını değiştirmemeniz gerekmektedir. Zira aşağıdaki örnek RIGHT JOIN kullanmamıza rağmen LEFT JOIN sonucunu döndürür.
SELECT m.*, md.musteri_detay_website FROM firmam.musteri_detay AS md RIGHT JOIN firmam.musteri AS m ON md.musteri_id = m.musteri_id WHERE 1
Sorgu Sonucu :
+------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | musteri_id | musteri_ad | musteri_soyad | musteri_telefon | musteri_email | musteri_durum | musteri_detay_website | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ | 1 | Ahmet | AY | 2125555555 | [email protected] | AKTIF | NULL | | 2 | Mehmet | YILDIZ | 2125555556 | [email protected] | AKTIF | NULL | | 3 | Ali | KİBAR | 2125555557 | [email protected] | AKTIF | NULL | | 4 | Mustafa | KIRIMLI | 4294967295 | [email protected] | AKTIF | http://mustafakirimli.com | | 5 | John | DOE | 2127777777 | [email protected] | AKTIF | NULL | | 6 | Jane | DOE | 2128888888 | [email protected] | DEAKTIF | NULL | +------------+------------+---------------+-----------------+-------------------------+---------------+---------------------------+ 6 rows in set (0.00 sec)
Sonuçlarda göründüğü gibi tablo yazım sırası sonuçları etkiliyor.
CROSS JOIN Kullanımı
MySQL CROSS JOIN, INNER JOIN ile aynı işlemi yapar.
MySQL JOIN İşlemlerinin Venn Şeması İle Gösterimi
JOIN işlemlerinin Venn Şeması ile gösterimini buradan (HTML5 ile hazırlandı resim değildir) inceleyebilirsiniz.
MySQL FULL OUTER JOIN İşlemi (MySQL FULL OUTER JOIN desteklemez simülasyon ile yapıyoruz)
MySQL ile FULL OUTER JOIN kullanmak için union, union all yada mutex table yöntemini kullanmanız gerekir. (detaylar gelecek)
FULL OUTER JOIN için kullandığım kaynak: http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/
ÇOK TEŞEKKÜR EDERİM.
MUHTEŞEM BİR PAYŞAŞIM OLMUŞ.
Join olayından oldum olası korktum. Öğrenemeyeceğimi sandım hep. Öğrenmek içinde ayrıntılı, püf noktalarının verildiği bir Türkçe makale bulamayacağımı sanmıştım. Ama bu yazı benim tabularımı yıktı. Çok teşekkürler.
peki şöyle bir sorgu nasıl olur
soldaki tabloda bir ürün var ve sağdaki tablodanda soldaki ürüne ait sadece tek bir belirlenmiş satırı getirmek istiyoruz. bunu mssql cross apply ile yapıyoruz ancak internetde çok araştırmama rağmen mysql karşılığını bulamadım. sizin bir çözümünüz varmı bununla ilgili ???
Merhaba nuknettin,
Tablolar 1:1 (one to one) şeklinde birbirlerine bağlıysa INNER JOIN, 1:n (one to n, one to many) olarak bağlıysa LEFT JOIN + soldaki tablo alanını GROUP BY ile olur.
Örnek senaryo üzerinde daha iyi anlatılır bu konu. Ayrıca özette olsa tablo yapını paylaşman gerekir. Sağ tablodan hangi veriyi (hangi sırayla) alacağının önemi var mı vs.
İyi Günler
ben örnek mssql sorgumu yazıyorum
bu veritabanını mysql e aktardım ve bu sorguyu mysql e çevirmekte sorun yaşıyorum
yani özetle ilk tablodaki otele ait 2.tablodan belirtmiş olduğum kriterlere göre ilk fiyatı, eğer varsa outer apply ile liste fiyatını ve yine outer apply ile varsa kampanyayı çekmek istiyorum yukarıdaki sql sorgusu mssql sorunsuz çalışıyor ancak mysql de bunu inner join ile japtığımda çok alakasız ve tek bir satır sonuç alabiliyorum
MySQL ‘de bulunan çözümünüzün Subquery olduğunu düşünüyorum. FROM alanında subquery kullanmak(en).
Ancak bu kadar subquery içeren ve bu denli büyük sorgunun performans açısından sıkıntı yaratma ihtimali yüksek sanırım.
bir deneyeceğim sonucu tekrar yazarım teşekkürler.
denedim ancak inner join ile aynı sonucu verdi sanırım sorguyu inner join ile çevirirken cross apply içinde kullandığım OTELTUR.ID = OID alanını dışarı almamdan kaynaklanıyor ancak bunu sorgunun içinde kullanmamın bir yolu yok sanırım. inner join ile çevirdiği sorgu aşağıdaki gibi ve sizin önderdiğinin sorguyuda onun altına yazıyorum sorguları biraz kısalttım çünkü bu sonucu elde edersem diğerinide çözerim sanıyorum.
Tavsiyem tabloları (sort dışında) OTELTUR tablosuna direkt join yaparak duruma göre ON clause ‘da yada WHERE clause ‘da filtreleme yapmanız.
Bu sorgu üzerinde harcadığımız tüm zaman eş zamanlı 10k üzerinde trafik aldığınızda boşa gidecektir. Eğer cache kullanacaksanız zaten bu kadar karmaşık sorguya gerek yok. İki yada üç ayrı sorguda almanızın daha yerinde olur.
Gerçekten tek sorgu yazmanız gerekmiyorsa kullanmayın derim. Sorgudan kaçmış gibi olmamak adına; biraz zaman ayırıp çözülebileceğini tahmin ediyorum.
İyi Günler
teşekkürler cevaplarınız için dediklerinizi bir deniyeceğim
Rica ederim umarım işe yarar. Ayrıca WEBGOSTER “1” bu şekilde degil orjinal sorgunuz degil mi?
hayır değil sanırım burada silinmiş
sanırım sorunun kaynağını buldum kullandığım inner join içerisindeki limit sınırlaması sonucunda sadece tekbir satır sonuç döndürdüğünden sadece 1 otele ait bilgiyi çekiyor. bu nedenle sadece bir sonuç dönüyordu bunu ayrı bir view oluşturana kadar farkedemedim onun dışında sorgu gayet hızlı çalışıyor şimdi acaba bu sorunu nasıl çözebiliriz :))
Limitsiz çektiğinizde sorunsuz çalışması gerekmiyor mu? ON clause alanında otel eşleştirmesi yapıyorsunuz.
Hızlıdan kastınız kaç ms? Vede kaç kayıtla. Sıkıntı yaratmayacak kadar hızlıysa tebrikler. Ama sorgunuzda bir çok alanda INDEX kullanamadan JOIN yapmak zorunda kalıyor MySQL.
Benim dediğimde olmaz muhtemelen. Sorgu içerisinde yapmak istiyorsunuz o otele ait limitlmeyi. SELECT alanında sub query ile çözmenize engel bir durum var mı?
sorgu içinde herbir row için subquery oluşturmak gerekiyor sizin dediğinizde ve inner joinde ise iç sorguda Otel.Id = Fiyatlar.OID kabul etmiyor bu yüzden en üstte bulduğu otele ait veriyi çekiyor. mysql en altta group by ifadesine izin veriyor ancak mssql sorgusu ile karşılaştırdığımda farklı sonuçlar olduğu aşikar. halen uğraşıyorum.
bu arada otel tablosnda 1900 kayıt fiyat tablosunda 40000 kayıt bulunuyor sonuç ise 0.163 sn
40.000 kayıt için ortalamanın üzerinde bir süre. Eğer sorgu webde çalışacaksa yük altında kaynak kullanımını ölçün derim.
Amazon.com 100ms yavaşladığında satışlarının %1 oranında düştüğünü söylüyor. “Latency matters. Amazon found every 100ms of latency cost them 1% in sales” sayfa yüklenme süresinin önemi
şuan içiçe sorgu deniyorum ancak yinede ana sorgudan gelecek id lerin içerisinde sadece fiyatı olanları çekmem gerek bu nasıl olacak group by kullanınca sorgu çok yavaşlıyor
hocam makale için teşekkürler, gerçekten faydalı.
ben çok merak ettiğim ve üzerinde çok kafa yorduğum bi durum var bilmiyorum yardımcı olabilir misiniz.
şimdi twitter tarzı üye takip sistemi olan bir site düşünün. kimin kimi takip ettiğini “takip” isimli bir tabloda tutuyor olalım.
takip_id—>takip_edilen_id—->takip_eden_id——>takip_tarihi
tarzında sütunlarımız olsun.
bir de kişilerin gerçekleştirmiş oldukları olaylara dair bir “olaylar” tablosu olsun. işte ahmet şuna yorum yaptı, mehmet şunu beğendi tarzında.
işte benim film burda kopuyor. her üyenin duvarında, takip ettiği kişilerin yapmış olduğu olayları (bunlar farklı bir kaç tabloda da tutuluyor olabilir) tarih sırasına göre nasıl dizerim.(facebook duvar mantığı) bir türlü bu mantığı çözemedim. benim takip ettiğim onlarca kişi olabilir. o onlarca kişinin id numaralarına göre “olaylar” ve ona benzer farklı bir kaç tabloda bir defada sorgu yapıp sonuçları tarihe göre nasıl listeleticem.
düşünmekten beynim durdu, belki de çok basit bir mantığı vardır ben bilmiyorum gerçekten bu konuda yardım ederseniz çok sevinicem.
Merhaba Hocam,
tek tabloda her 1 öğrencinin 42 soruya verdiği 20 bin civarında cevaptan kullanıcıları ve 42 cevabı yan yana nasıl sıralayabilirim?
görüntüyü şurda soruya eklemiştim: http://www.uzmansorusu.com/soru/2946/inner-join-ile-birlestirme
şimdiden tşkler. iyi çalışmalar…
Merhaba Hakan bey,
Sanırım her satırda o öğrenciye ait 42 soruyu ve cevabı almak istiyorsunuz. Bunu yapmak performans açısından çokta mantıklı olmayabilir.
Eğer tek seferde almanız zorunlu değilse farklı satırlarda (alt alta) alıp ekrana yan yana basmak daha iyi sonuç almanızı sağlar. İllaki yapmanız gerekiyorsa group_concat, soru sayısı kadar join yapma (max join limitine takılabilirsiniz) gibi yöntemler deneyebilirsiniz. Ama size önerim gb seviyesinde ve milyona yakın kayıtta performans karşılaştırması yapmanız olacaktır.
Saygılarımla
merhaba merak ettiğim birşey var yardımcı olabilirseniz sevinirim
10 tane öğrencinin bulunduğu bir sınıf var fakat bu öğrencilerin hepsi 20 dersten farklı dersleri alyor atıyorum 2şer ders alıyorlar.bu derslerdende 4 er sınav olmuşlar. ben tek tabloda bir öğrencinin aldığı derslerin sınav toplamlarını gösterebilirmiyim
bir join kullanımı arıyordum nerelere geldim ya. neyin kafası yaa bu…
merhaba güzel makale, tebrikler.
şöylebir sorunum var.
diyelim ki; urunler ve gruplar şeklinde tablolalarımız var.
CREATE TABLE IF NOT EXISTS `grup` (
`urunid` mediumint(8) NOT NULL,
`grup` int(2) NOT NULL,
PRIMARY KEY (`urunid`),
KEY `grup` (`grup`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `grup` (`urunid`, `grup`) VALUES
(2, 102),
(1, 104);
CREATE TABLE IF NOT EXISTS `urun` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`urun` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `urun` (`id`, `urun`) VALUES
(1, ‘mouse’),
(2, ‘klavye’),
(3, ‘cpu’);
bir sorgu ile 104 grubundaki ürünler hariç tüm ürünlerin gelmesini istiyorum. örnekte cpu içingrup belirlenmemiş, onun da null gelmesi gerekli.
şu şekilde getirebiliyorum;
SELECT * FROM grup RIGHT JOIN urun ON urunid = id
WHERE ( grup !=104 OR grup IS NULL)
ama, yukarıda verdiğiniz “left join between” örneğindeki gibi uygularsam cpu kaydı gelmiyor.
SELECT * FROM grup RIGHT JOIN urun ON urunid = id and grup!=104 gibi.
SELECT u.* , s.satis_miktar
FROM firmam.urun AS u
LEFT JOIN firmam.satis AS s ON u.urun_id = s.urun_id
AND s.satis_tarih BETWEEN ‘2010-12-01 00:00:00’ AND ‘2010-12-01 23:59:59’
WHERE 1
Bu sorgu örneği için teşekkurler. and kısmından sonraki kuşula benzer bir koşulu where altına yazıyordum istediğim bilgiler eksik geliyordu.
Gerçekten güzel bir anlatım olmuş.
$sqql=”SELECT I.* , E.* FROM motor AS I LEFT JOIN motor_ek AS E ON I.Idd=E.Idd WHERE I.sts=2″; gibi bir sorgunun sonuçlarında Idd sütunu sonuçlarda dönmüyor hem Idd sütununu birleştirmede kullanıp hem dönen sonuçlarda görüntülemenin yolu yokmu. Bu arada çalışmalarınız için teşekkürler
Merhaba,
2 tablom var, uyeler ve yorumlar.
uyeler: id, kulladi, kullsif, mail
yorumlar: id, yorum, mail
Ben yorum yapan kişinin mailinden uyeler tablosuna gidip o maile ait kulladi nı bulup onu yazdığı yorumun yanına yazdırmaya çalışıyorum.
2 tane yorumu kayıtlı. Birini Emir Genç kullanıcısı yapmış diğerini Ahmet Genç kullanıcısı yapmış. yorumlar tablosunda bu şöyle kayıtlı:
id: 1
yorum: selam ben Emir.
mail: [email protected]
DİĞERİ
id: 2
yorum: Merhaba Emir
mail: [email protected]
Buradaki maillerden uyelere gidip isimleri seçtiğimde yalnıca tek ismi seçiyorve yazdırıyor. iki yorum alt alta ikisinde de Emre Genç ya da Ahmet Genç yazıyor. 2gündür kayboldum kodların içinde ve çıkamadım bir türlü, yardım rica ediyorum.
Kullandığım kod:
$sorgu = mysql_query(“SELECT kulladi FROM uyeler INNER JOIN yorumlar ON yorumlar.mail = uyeler.mail”);
$sonuc = mysql_fetch_array($sorgu);
echo “$sonuc[kulladi]”;
iyi çalışmalar benim bir sorum olacaktı. Ben bir blog sayfası yapıyorum blogların göründüğü yerde o blok hakkında kaçtane yorum yapılmış onu da göstercek Şu şekilde bir Sorgu Yaptım
SELECT tbblog.*,Count(tbyorum.blogid) AS YORUMSAYISI FROM tbblog INNER JOIN tbyorum ON tbblog.id=tbyorum.blogid
bu şekilde sorgu yaptım lakin bu sorguda hem tbyorum tablosunda blogid kolonuna bakmadan ne kadar yorum varsa o kadar gösteriyor hemde blog tablomdaki verilerden sadece birtanesini gösteriyor. İstediğimi nasıl yapabilirm? yardım ederseniz çok sevinirim
Çok güzel ve faydalı bir makale olmuş teşekkürler hocam. Bide bu veritabanı şablonlarını neyle oluşturuyorsunuz onuda söylerseniz sevinirim.
Dolu, gerçekten işe yarar bir yazı olmuş. Çok istifade ettim, teşekkürler.