Bölüm 1 - Birleşimler ve Birlikler
Bu cevap şunları kapsamaktadır:
- Bölüm 1
- Bir iç birleşim kullanarak iki veya daha fazla tabloya katılma ( Ek bilgi için wikipedia girişine bakın )
- Birlik sorgusu nasıl kullanılır?
- Sol ve Sağ Dış Birleşimler (bu stackOverflow yanıtı , birleştirme türlerini tanımlamak için mükemmeldir)
- Kesişen sorgular (ve veritabanınız onları desteklemiyorsa bunları nasıl çoğaltacağınız) - bu bir SQL-Server ( bkz. Bilgi ) işlevidir ve her şeyi ilk başta yazmamın nedeninin bir parçasıdır .
- Bölüm 2
- Alt sorgular - ne oldukları, nerede kullanılabilecekleri ve nelere dikkat edilecekleri
- Kartezyen AKA'ya katıldı - Ah, sefalet!
Veritabanındaki birden çok tablodan veri almanın birkaç yolu vardır. Bu cevapta ANSI-92 birleştirme sözdizimi kullanacağım. Bu eski ANSI-89 sözdizimi kullanın orada diğer öğreticiler bir dizi farklı olabilir (eğer 89 için kullanılıyorsa ve çok daha az sezgisel görünebilir - ama tüm söyleyebileceğim denemek için) olduğu gibi çok daha kolay sorguların ne zaman karmaşıklaşmaya başladığını anlamak. Neden kullanmalıyım? Performans kazancı var mı? Kısa cevap hayır, ama bir sen buna alışması kez daha kolay okunur. Bu sözdizimini kullanarak diğer kişiler tarafından yazılan sorguları okumak daha kolaydır.
Ayrıca, hangi arabaların mevcut olduğunu takip etmek için bir veritabanına sahip küçük bir avlu kavramını kullanacağım. Sahibi, BT Bilgisayarı adamı olarak sizi işe aldı ve ona bir şapka düştüğünde istediği verileri bırakabilmenizi bekliyor.
Son tablo tarafından kullanılacak bir dizi arama tablosu yaptım. Bu bize çalışmak için makul bir model verecektir. Başlamak için, sorgularımı aşağıdaki yapıya sahip örnek bir veritabanına çalıştıracağım. Başlarken yapılan yaygın hataları düşünmeye ve onlarla neyin yanlış gittiğini açıklamaya çalışacağım - tabii ki bunları nasıl düzelteceğimizi göstereceğim.
İlk tablo sadece bir renk listesidir, böylece araba bahçesinde hangi renklere sahip olduğumuzu biliriz.
mysql> create table colors(id int(3) not null auto_increment primary key,
-> color varchar(15), paint varchar(10));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | varchar(15) | YES | | NULL | |
| paint | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> insert into colors (color, paint) values ('Red', 'Metallic'),
-> ('Green', 'Gloss'), ('Blue', 'Metallic'),
-> ('White' 'Gloss'), ('Black' 'Gloss');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from colors;
+----+-------+----------+
| id | color | paint |
+----+-------+----------+
| 1 | Red | Metallic |
| 2 | Green | Gloss |
| 3 | Blue | Metallic |
| 4 | White | Gloss |
| 5 | Black | Gloss |
+----+-------+----------+
5 rows in set (0.00 sec)
Markalar tablosu, otomobilin dışarıda satabileceği farklı markaları tanımlar.
mysql> create table brands (id int(3) not null auto_increment primary key,
-> brand varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from brands;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| brand | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> insert into brands (brand) values ('Ford'), ('Toyota'),
-> ('Nissan'), ('Smart'), ('BMW');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from brands;
+----+--------+
| id | brand |
+----+--------+
| 1 | Ford |
| 2 | Toyota |
| 3 | Nissan |
| 4 | Smart |
| 5 | BMW |
+----+--------+
5 rows in set (0.00 sec)
Model tablosu farklı araba tiplerini kapsayacaktır, bunun için gerçek araba modelleri yerine farklı araba tiplerini kullanmak daha basit olacaktır.
mysql> create table models (id int(3) not null auto_increment primary key,
-> model varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from models;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| model | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> insert into models (model) values ('Sports'), ('Sedan'), ('4WD'), ('Luxury');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from models;
+----+--------+
| id | model |
+----+--------+
| 1 | Sports |
| 2 | Sedan |
| 3 | 4WD |
| 4 | Luxury |
+----+--------+
4 rows in set (0.00 sec)
Ve son olarak, diğer tüm tabloları birleştirmek için, her şeyi birbirine bağlayan tablo. Kimlik alanı aslında arabaları tanımlamak için kullanılan benzersiz lot numarasıdır.
mysql> create table cars (id int(3) not null auto_increment primary key,
-> color int(3), brand int(3), model int(3));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from cars;
+-------+--------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | int(3) | YES | | NULL | |
| brand | int(3) | YES | | NULL | |
| model | int(3) | YES | | NULL | |
+-------+--------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> insert into cars (color, brand, model) values (1,2,1), (3,1,2), (5,3,1),
-> (4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> select * from cars;
+----+-------+-------+-------+
| id | color | brand | model |
+----+-------+-------+-------+
| 1 | 1 | 2 | 1 |
| 2 | 3 | 1 | 2 |
| 3 | 5 | 3 | 1 |
| 4 | 4 | 4 | 2 |
| 5 | 2 | 2 | 3 |
| 6 | 3 | 5 | 4 |
| 7 | 4 | 1 | 3 |
| 8 | 2 | 2 | 1 |
| 9 | 5 | 2 | 3 |
| 10 | 4 | 5 | 1 |
+----+-------+-------+-------+
10 rows in set (0.00 sec)
Bu, bize farklı türlerdeki birleşimlerin aşağıdaki örneklerini kapsamak için yeterli veri (umarım) verecek ve aynı zamanda onları değerli kılmak için yeterli veri verecektir.
Bu nedenle, patron sahip olduğu tüm spor otomobillerin kimliklerini bilmek istiyor .
Bu basit bir iki masa birleşimidir. Modeli ve tabloyu mevcut stok ile tanımlayan bir tablonuz var. Gördüğünüz gibi, veri model
sütun cars
tabloya ilgilidir models
sütununun cars
elimizdeki masaya. Şimdi, biz modelleri tablosu bir kimliği olduğunu biliyoruz 1
için Sports
öylesine katılmak yazmanıza olanak tanır.
select
ID,
model
from
cars
join models
on model=ID
Yani bu sorgu iyi görünüyor değil mi? İki tabloyu belirledik ve ihtiyacımız olan bilgileri içerdik ve hangi sütunlara katılacağınızı doğru bir şekilde tanımlayan bir birleştirme kullandık.
ERROR 1052 (23000): Column 'ID' in field list is ambiguous
Ah hayır! İlk sorgumuzda bir hata! Evet, ve bir erik. Gördüğünüz gibi, sorgu gerçekten doğru sütunlara sahip, ancak bazıları her iki tabloda da var, bu yüzden veritabanı ne demek istediğimiz ve nerede olduğumuzu karıştırıyor. Bunu çözmek için iki çözüm var. Birincisi hoş ve basit, tableName.columnName
veritabanına tam olarak ne demek istediğimizi söylemek için kullanabiliriz :
select
cars.ID,
models.model
from
cars
join models
on cars.model=models.ID
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
| 2 | Sedan |
| 4 | Sedan |
| 5 | 4WD |
| 7 | 4WD |
| 9 | 4WD |
| 6 | Luxury |
+----+--------+
10 rows in set (0.00 sec)
Diğeri muhtemelen daha sık kullanılır ve masa takma adı olarak adlandırılır. Bu örnekteki tabloların güzel ve kısa basit isimleri vardır, ancak böyle bir şey yazmak KPI_DAILY_SALES_BY_DEPARTMENT
muhtemelen hızlı bir şekilde eskidir, bu nedenle basit bir yol tabloyu şu şekilde adlandırmaktır:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
Şimdi, isteğe geri dönelim. Gördüğünüz gibi, ihtiyacımız olan bilgilere sahibiz, ancak istenmeyen bilgilerimiz de var, bu yüzden ifadeye yalnızca Spor arabaları istendiği gibi bir yer cümlesi eklememiz gerekiyor. Tablo adlarını defalarca kullanmak yerine tablo diğer yöntemini tercih ettiğim için, bu noktadan sonra buna yapışacağım.
Açıkçası, sorgumuza where cümlesi eklememiz gerekiyor. Spor arabaları ID=1
veya ile tanımlayabiliriz model='Sports'
. Kimlik endekslendiğinde ve birincil anahtar (ve daha az yazarak) olduğundan, sorgumuzda bunu kullanalım.
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
Bingo! Patron mutlu. Tabii ki, bir patron olmak ve istediği şeyden asla mutlu olmamak, bilgiye bakar, sonra renkleri de istediğimi söylüyor .
Tamam, bu yüzden sorgumuzun zaten iyi bir parçası var, ancak renkler olan üçüncü bir tablo kullanmamız gerekiyor. Şimdi, ana bilgi tablomuz cars
araç renk kimliğini saklar ve bu, renk kimliği sütununa geri bağlanır. Yani, orijinaline benzer şekilde üçüncü bir masaya katılabiliriz:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
Kahretsin, tablo doğru bir şekilde birleştirilmiş ve ilgili sütunlar birbirine bağlı olmasına rağmen, yeni bağladığımız yeni tablodan gerçek bilgileri almayı unuttuk .
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
+----+--------+-------+
4 rows in set (0.00 sec)
Tamam, bu bir an için sırtımızdan çıkan patron. Şimdi, bunlardan bazılarını biraz daha ayrıntılı olarak açıklayalım. Gördüğünüz gibi, from
ifademizdeki cümle ana tabloyu bağlar (genellikle arama veya boyut tablosu yerine bilgi içeren bir tablo kullanırım. Sorgu, tüm tablolar ile de çalışır, ancak daha az anlamlı olur birkaç ay içinde okumak için bu sorguya geri dönüyoruz, bu yüzden iyi ve anlaşılması kolay bir sorgu yazmaya çalışmak en iyisidir - sezgisel olarak yerleştirin, her şeyin açık olması için güzel girinti kullanın Başkalarına öğretmeye devam ederseniz, bu özellikleri sorgularına yerleştirmeye çalışın - özellikle de sorun gidermeye başlayacaksanız.
Giderek daha fazla tabloyu bu şekilde bağlamaya devam etmek tamamen mümkündür.
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
İfadede birden fazla sütuna katılmak isteyebileceğimiz bir tablo eklemeyi unuttum, ancak join
bir örnek. Eğer models
tablo bu nedenle markaya özel modeller vardı ve ayrıca adında bir sütun vardı brand
geri bağlantılı brands
tabloda ID
alanında, bu şekilde yapılabilir:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
and b.brand=d.ID
where
b.ID=1
Gördüğünüz gibi, yukarıdaki sorgu yalnızca birleştirilmiş tabloları ana cars
tabloya bağlamakla kalmaz, aynı zamanda zaten birleştirilmiş tablolar arasındaki birleştirmeleri de belirtir. Bu yapılmadıysa, sonuç kartezyen bir birleşim olarak adlandırılır - dba kötüdür. Kartezyen birleştirme, bilgi veritabanına sonuçları nasıl sınırlandıracağını söylemediği için satırların döndürüldüğü yerdir, bu nedenle sorgu ölçütlere uyan tüm satırları döndürür .
Kartezyen birleştirme örneği vermek için aşağıdaki sorguyu çalıştıralım:
select
a.ID,
b.model
from
cars a
join models b
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 1 | Sedan |
| 1 | 4WD |
| 1 | Luxury |
| 2 | Sports |
| 2 | Sedan |
| 2 | 4WD |
| 2 | Luxury |
| 3 | Sports |
| 3 | Sedan |
| 3 | 4WD |
| 3 | Luxury |
| 4 | Sports |
| 4 | Sedan |
| 4 | 4WD |
| 4 | Luxury |
| 5 | Sports |
| 5 | Sedan |
| 5 | 4WD |
| 5 | Luxury |
| 6 | Sports |
| 6 | Sedan |
| 6 | 4WD |
| 6 | Luxury |
| 7 | Sports |
| 7 | Sedan |
| 7 | 4WD |
| 7 | Luxury |
| 8 | Sports |
| 8 | Sedan |
| 8 | 4WD |
| 8 | Luxury |
| 9 | Sports |
| 9 | Sedan |
| 9 | 4WD |
| 9 | Luxury |
| 10 | Sports |
| 10 | Sedan |
| 10 | 4WD |
| 10 | Luxury |
+----+--------+
40 rows in set (0.00 sec)
Tanrım, bu çirkin. Ancak, veritabanı ile ilgili olarak, tam olarak ne istenir. Sorguda, biz istedi ID
gelen cars
ve model
gelen models
. Biz belirtmedi Ancak, nasıl tabloları katılmak için, veritabanı karşıladığında her ilk tablodan satır her ikinci tablodan sıranın.
Tamam, patron geri döndü ve tekrar daha fazla bilgi istiyor. Aynı listeyi istiyorum, ama aynı zamanda 4WD'leri de içeriyorum .
Ancak bu, bunu başarmanın iki farklı yoluna bakmak için bize harika bir bahane verir. Nereye bu maddeye başka bir koşul ekleyebiliriz:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
or b.ID=3
Yukarıdakiler mükemmel bir şekilde çalışsa da, farklı bir şekilde bakalım, bu bir union
sorgunun nasıl çalışacağını göstermek için harika bir bahane .
Aşağıdakilerin tüm Spor arabalarını iade edeceğini biliyoruz:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
Ve aşağıdaki tüm 4WD'leri döndürür:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
Bu nedenle, union all
aralarına bir cümle eklenerek , ikinci sorgunun sonuçları ilk sorgunun sonuçlarına eklenir.
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
union all
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
| 5 | 4WD | Green |
| 7 | 4WD | White |
| 9 | 4WD | Black |
+----+--------+-------+
7 rows in set (0.00 sec)
Gördüğünüz gibi, önce ilk sorgunun sonuçları, ardından ikinci sorgunun sonuçları döndürülür.
Bu örnekte, elbette ilk sorguyu kullanmak çok daha kolay olurdu, ancak union
sorgular belirli durumlar için harika olabilir. Bunlar, kolayca birleştirilemeyen tablolardan tablolardan belirli sonuçlar döndürmek için harika bir yoldur - veya bu nedenle tamamen ilgisiz tablolar. Ancak, uyulması gereken birkaç kural vardır.
- İlk sorgudaki sütun türleri, aşağıdaki diğer tüm sorgulardaki sütun türleriyle eşleşmelidir.
- İlk sorgudaki sütunların adları sonuç kümesinin tamamını tanımlamak için kullanılacaktır.
- Her sorgudaki sütun sayısı aynı olmalıdır.
Şimdi ve ile arasındaki farkın ne olduğunu merak ediyor olabilirsiniz . Bir sorgu yinelenenleri kaldıracak, bir ise olmayacak. Bu kullanırken küçük bir performans isabet olduğunu anlama geliyor üzerinde ama sonuç değerinde o olabilir - Ben bu olsa içinde böyle şeylere üzerinde spekülasyon olmaz.union
union all
union
union all
union
union all
Bu notta, burada bazı ek notlara dikkat etmek gerekebilir.
- Sonuçları sipariş etmek istersek, bir kullanabiliriz,
order by
ancak artık takma adı kullanamazsınız. Yukarıdaki sorguda, her iki sorguda da aynı takma ad kullanılmış olsa bile order by a.ID
, sonuç eklenmesi bir hatayla sonuçlanır - sonuçlar söz konusu olduğunda, sütun ID
yerine çağrılır a.ID
.
- Sadece bir
order by
cümle yapabiliriz ve bu son cümle gibi olmalıdır.
Sonraki örnekler için, tablolarımıza birkaç satır daha ekliyorum.
Holden
Markalar tablosuna ekledim . Ben de renkler tablosunda hiçbir referansı olan - değerine cars
sahip bir satır ekledim .color
12
Tamam, patron tekrar geri döndü, havlıyor istekleri - * Taşımakta olduğumuz her markanın bir sayısını ve araba sayısını istiyorum! `` - Tipik olarak, tartışmamızın ilginç bir bölümüne gidiyoruz ve patron daha fazla iş istiyor .
Doğru, yani ilk yapmamız gereken olası markaların tam bir listesini almak.
select
a.brand
from
brands a
+--------+
| brand |
+--------+
| Ford |
| Toyota |
| Nissan |
| Smart |
| BMW |
| Holden |
+--------+
6 rows in set (0.00 sec)
Şimdi, bunu otomobil masamıza kattığımızda şu sonucu alıyoruz:
select
a.brand
from
brands a
join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Nissan |
| Smart |
| Toyota |
+--------+
5 rows in set (0.00 sec)
Tabii ki bu bir sorun - Holden
eklediğim güzel markanın herhangi bir sözünü görmüyoruz .
Bunun nedeni bir birleştirmenin her iki tabloda da eşleşen satırları aramasıdır . Otomobillerde herhangi bir veri Holden
olmadığı için iade edilmez. Birleştirme kullanabileceğimiz yer burası outer
. Bu , diğer tabloda eşleştirilip eşleştirilmemelerine bakılmaksızın tüm sonuçları bir tablodan döndürür :
select
a.brand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Holden |
| Nissan |
| Smart |
| Toyota |
+--------+
6 rows in set (0.00 sec)
Artık buna sahibiz, bir sayı elde etmek ve patronu bir anlığına arkadan almak için hoş bir toplama işlevi ekleyebiliriz.
select
a.brand,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+--------------+
| brand | countOfBrand |
+--------+--------------+
| BMW | 2 |
| Ford | 2 |
| Holden | 0 |
| Nissan | 1 |
| Smart | 1 |
| Toyota | 5 |
+--------+--------------+
6 rows in set (0.00 sec)
Ve bununla birlikte, patron kaçıyor.
Şimdi, bunu daha ayrıntılı olarak açıklamak için, dış birleşimler left
veya right
tipinde olabilir. Sol veya Sağ hangi tablonun tam olarak dahil edileceğini tanımlar . A left outer join
, soldaki tablodaki tüm satırları içerirken (tahmin ettiniz) a right outer join
, sağdaki tablodaki tüm sonuçları sonuçlara getirir.
Bazı veritabanları, her iki tablodan full outer join
da sonuçları (eşleşen olsun olmasın) geri getirmesine izin verir , ancak bu tüm veritabanlarında desteklenmez.
Şimdi, muhtemelen bu noktada anlıyorum, bir sorguda birleştirme türlerini birleştirip birleştiremeyeceğinizi merak ediyorsunuz - ve cevap evet, kesinlikle yapabilirsiniz.
select
b.brand,
c.color,
count(a.id) as countOfBrand
from
cars a
right outer join brands b
on b.ID=a.brand
join colors c
on a.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| Ford | Blue | 1 |
| Ford | White | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| BMW | Blue | 1 |
| BMW | White | 1 |
+--------+-------+--------------+
9 rows in set (0.00 sec)
Peki, bu beklenen sonuçlar neden olmasın? Çünkü arabalardan markalara dış birleşimi seçmiş olsak da, renklerin birleşiminde belirtilmedi - böylece belirli bir birleşim sadece her iki tabloda eşleşen sonuçları geri getirecektir.
Beklediğimiz sonuçları almak için işe yarayacak sorgu:
select
a.brand,
c.color,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
left outer join colors c
on b.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| BMW | Blue | 1 |
| BMW | White | 1 |
| Ford | Blue | 1 |
| Ford | White | 1 |
| Holden | NULL | 0 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| Toyota | NULL | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
+--------+-------+--------------+
11 rows in set (0.00 sec)
Gördüğümüz gibi, sorguda iki dış birleşimimiz var ve sonuçlar beklendiği gibi geliyor.
Şimdi, sorduğunuz bu tür diğer birleşimlere ne dersiniz? Kavşaklar ne olacak?
Eh, tüm veritabanları desteklemez, intersection
ancak hemen hemen tüm veritabanları bir birleştirme (veya en azından en iyi şekilde yapılandırılmış bir ifade) yoluyla bir kavşak oluşturmanıza izin verecektir.
Bir Kesişim, union
yukarıda tarif edilene benzer bir birleşim türüdür - ancak fark, yalnızca birleşmenin birleştirdiği çeşitli ayrı sorgular arasında özdeş olan (ve özdeş demek istediğim) veri satırlarını döndürmesidir. Yalnızca her açıdan özdeş olan satırlar döndürülür.
Basit bir örnek şöyle olacaktır:
select
*
from
colors
where
ID>2
intersect
select
*
from
colors
where
id<4
Normal bir union
sorgu tablonun tüm satırlarını döndürür (ilk sorgu her şeyi döndürür ID>2
ve ikinci her şey sahip olur ID<4
), bu da tam küme ile sonuçlanır, ancak kesişen bir sorgu yalnızca id=3
her iki ölçütü karşıladığından satır eşleşmesini döndürür .
Şimdi, veritabanınız bir intersect
sorguyu desteklemiyorsa , yukarıdakiler aşağıdaki sorgu ile kolayca gerçekleştirilebilir:
select
a.ID,
a.color,
a.paint
from
colors a
join colors b
on a.ID=b.ID
where
a.ID>2
and b.ID<4
+----+-------+----------+
| ID | color | paint |
+----+-------+----------+
| 3 | Blue | Metallic |
+----+-------+----------+
1 row in set (0.00 sec)
Bir kesişim sorgusunu doğal olarak desteklemeyen bir veritabanı kullanarak iki farklı tablo arasında bir kavşak gerçekleştirmek istiyorsanız , tabloların her sütununda bir birleştirme oluşturmanız gerekir .