Teil 1 - Beitritte und Gewerkschaften
Diese Antwort umfasst:
- Teil 1
- Teil 2
- Unterabfragen - was sie sind, wo sie verwendet werden können und worauf zu achten ist
- Cartesian tritt der AKA bei - Oh, das Elend!
Es gibt verschiedene Möglichkeiten, Daten aus mehreren Tabellen in einer Datenbank abzurufen. In dieser Antwort verwende ich die ANSI-92-Join-Syntax. Dies unterscheidet sich möglicherweise von einer Reihe anderer Tutorials, die die ältere ANSI-89-Syntax verwenden (und wenn Sie an 89 gewöhnt sind, scheint dies viel weniger intuitiv zu sein - aber ich kann nur sagen, es zu versuchen), da es viel einfacher ist zu verstehen, wann die Abfragen komplexer werden. Warum es benutzen? Gibt es einen Leistungsgewinn? Die kurze Antwort lautet nein, aber es ist einfacher zu lesen, wenn Sie sich daran gewöhnt haben. Mit dieser Syntax ist es einfacher, Abfragen zu lesen, die von anderen Personen geschrieben wurden.
Ich werde auch das Konzept eines kleinen Karyards verwenden, der über eine Datenbank verfügt, um zu verfolgen, welche Autos verfügbar sind. Der Eigentümer hat Sie als seinen IT-Computer-Mitarbeiter eingestellt und erwartet, dass Sie ihm die Daten, nach denen er fragt, im Handumdrehen löschen können.
Ich habe eine Reihe von Nachschlagetabellen erstellt, die vom Final Table verwendet werden. Dies gibt uns ein vernünftiges Modell, nach dem wir arbeiten können. Zu Beginn führe ich meine Abfragen für eine Beispieldatenbank mit der folgenden Struktur aus. Ich werde versuchen, an häufige Fehler zu denken, die beim Start gemacht werden, und erklären, was mit ihnen schief geht - und natürlich zeigen, wie man sie korrigiert.
Die erste Tabelle ist einfach eine Farbliste, damit wir wissen, welche Farben wir im Autohof haben.
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)
Die Markentabelle identifiziert die verschiedenen Marken der Autos, die Caryard möglicherweise verkaufen könnte.
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)
Die Modelltabelle deckt verschiedene Fahrzeugtypen ab. Es wird einfacher sein, unterschiedliche Fahrzeugtypen als tatsächliche Fahrzeugmodelle zu verwenden.
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)
Und schließlich, um all diese anderen Tische zusammenzubinden, den Tisch, der alles zusammenhält. Das ID-Feld ist tatsächlich die eindeutige Chargennummer, mit der Autos identifiziert werden.
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)
Dies gibt uns genügend Daten (ich hoffe), um die folgenden Beispiele für verschiedene Arten von Verknüpfungen abzudecken, und gibt auch genügend Daten, damit sie sich lohnen.
Der Chef möchte also die IDs aller Sportwagen kennen, die er hat .
Dies ist ein einfacher Join mit zwei Tabellen. Wir haben eine Tabelle, die das Modell und die Tabelle mit dem verfügbaren Bestand identifiziert. Wie Sie sehen können, beziehen sich die Daten in der modelSpalte der carsTabelle auf die modelsSpalte der carsTabelle, die wir haben. Jetzt wissen wir, dass die Modelltabelle eine ID von 1für hat, Sportsalso schreiben wir den Join.
select
ID,
model
from
cars
join models
on model=ID
Diese Abfrage sieht also gut aus, oder? Wir haben die beiden Tabellen identifiziert und enthalten die benötigten Informationen. Wir verwenden einen Join, der korrekt angibt, an welchen Spalten verbunden werden soll.
ERROR 1052 (23000): Column 'ID' in field list is ambiguous
Oh nein! Ein Fehler in unserer ersten Abfrage! Ja, und es ist eine Pflaume. Sie sehen, die Abfrage hat zwar die richtigen Spalten, aber einige davon sind in beiden Tabellen vorhanden, sodass die Datenbank verwirrt darüber ist, welche Spalte wir tatsächlich meinen und wo. Es gibt zwei Lösungen, um dies zu lösen. Das erste ist nett und einfach, wir können verwenden tableName.columnName, um der Datenbank genau zu sagen, was wir meinen, so:
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)
Das andere wird wahrscheinlich häufiger verwendet und als Tabellenaliasing bezeichnet. Die Tabellen in diesem Beispiel haben nette und kurze einfache Namen, aber das Eingeben von so etwas KPI_DAILY_SALES_BY_DEPARTMENTwürde wahrscheinlich schnell alt werden. Eine einfache Möglichkeit besteht darin, die Tabelle wie folgt zu benennen:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
Nun zurück zur Anfrage. Wie Sie sehen, haben wir die Informationen, die wir benötigen, aber wir haben auch Informationen, die nicht angefordert wurden. Daher müssen wir eine where-Klausel in die Erklärung aufnehmen, um nur die Sportwagen zu erhalten, wie sie angefordert wurden. Da ich die Tabellenalias-Methode bevorzuge, anstatt die Tabellennamen immer wieder zu verwenden, werde ich mich ab diesem Punkt daran halten.
Natürlich müssen wir unserer Abfrage eine where-Klausel hinzufügen. Wir können Sportwagen entweder durch ID=1oder identifizieren model='Sports'. Da die ID indiziert ist und der Primärschlüssel (und zufällig weniger eingegeben wird), können Sie dies in unserer Abfrage verwenden.
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! Der Chef ist glücklich. Da er ein Chef ist und nie glücklich mit dem ist, wonach er gefragt hat, schaut er sich die Informationen an und sagt dann, ich möchte auch die Farben .
Okay, wir haben einen Großteil unserer Abfrage bereits geschrieben, aber wir müssen eine dritte Tabelle verwenden, die Farben enthält. In unserer Hauptinformationstabelle wird nun carsdie Fahrzeugfarb-ID gespeichert und diese führt zurück zur Spalte Farb-ID. Ähnlich wie beim Original können wir uns also einer dritten Tabelle anschließen:
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)
Verdammt, obwohl die Tabelle korrekt verknüpft und die zugehörigen Spalten verknüpft waren, haben wir vergessen, die tatsächlichen Informationen aus der neuen Tabelle abzurufen, die wir gerade verknüpft haben.
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)
Richtig, das ist für einen Moment der Boss von unserem Rücken. Um dies etwas näher zu erläutern. Wie Sie sehen können, fromverknüpft die Klausel in unserer Anweisung unsere Haupttabelle (ich verwende häufig eine Tabelle, die Informationen anstelle einer Nachschlagetabelle oder Dimensionstabelle enthält. Die Abfrage funktioniert genauso gut, wenn alle Tabellen vertauscht sind, ist aber weniger sinnvoll, wenn Wir kommen auf diese Abfrage zurück, um sie in ein paar Monaten zu lesen. Daher ist es oft am besten, eine Abfrage zu schreiben, die schön und leicht zu verstehen ist. Legen Sie sie intuitiv an und verwenden Sie einen schönen Einzug, damit alles so klar wie möglich ist Wenn Sie andere unterrichten, versuchen Sie, diese Eigenschaften in ihre Abfragen einzubinden - insbesondere, wenn Sie Fehler beheben.
Es ist durchaus möglich, immer mehr Tabellen auf diese Weise zu verknüpfen.
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
Während ich vergessen habe, eine Tabelle aufzunehmen, in der wir möglicherweise mehr als eine Spalte in die joinAnweisung einfügen möchten , ist hier ein Beispiel. Wenn die modelsTabelle markenspezifische Modelle und daher auch eine Spalte mit dem Namen hat, branddie mit der brandsTabelle auf dem IDFeld verknüpft ist , könnte dies folgendermaßen geschehen:
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
Sie können sehen, dass die obige Abfrage nicht nur die verknüpften Tabellen mit der carsHaupttabelle verknüpft , sondern auch Verknüpfungen zwischen den bereits verknüpften Tabellen angibt. Wenn dies nicht getan wurde, wird das Ergebnis als kartesische Verknüpfung bezeichnet - was dba für schlecht spricht. Bei einem kartesischen Join werden Zeilen zurückgegeben, da die Informationen der Datenbank nicht mitteilen, wie die Ergebnisse eingeschränkt werden sollen. Daher gibt die Abfrage alle Zeilen zurück, die den Kriterien entsprechen.
Um ein Beispiel für eine kartesische Verknüpfung zu geben, führen Sie die folgende Abfrage aus:
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)
Guter Gott, das ist hässlich. In Bezug auf die Datenbank ist es jedoch genau das , wonach gefragt wurde. In der Abfrage haben wir nach dem IDvon carsund dem modelvon gefragt models. Da wir jedoch nicht angegeben haben, wie die Tabellen verknüpft werden sollen, hat die Datenbank jede Zeile aus der ersten Tabelle mit jeder Zeile aus der zweiten Tabelle abgeglichen .
Okay, der Chef ist zurück und möchte wieder mehr Informationen. Ich möchte die gleiche Liste, aber auch 4WDs darin enthalten .
Dies gibt uns jedoch eine gute Ausrede, zwei verschiedene Wege zu betrachten, um dies zu erreichen. Wir könnten der where-Klausel eine weitere Bedingung hinzufügen:
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
Obwohl das oben Genannte perfekt funktioniert, sehen wir es uns anders an. Dies ist eine gute Ausrede, um zu zeigen, wie eine unionAbfrage funktioniert.
Wir wissen, dass im Folgenden alle Sportwagen zurückgegeben werden:
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
Und das Folgende würde alle 4WDs zurückgeben:
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
Durch Hinzufügen einer union allKlausel zwischen ihnen werden die Ergebnisse der zweiten Abfrage an die Ergebnisse der ersten Abfrage angehängt.
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)
Wie Sie sehen, werden die Ergebnisse der ersten Abfrage zuerst zurückgegeben, gefolgt von den Ergebnissen der zweiten Abfrage.
In diesem Beispiel wäre es natürlich viel einfacher gewesen, einfach die erste Abfrage zu verwenden, aber unionAbfragen können für bestimmte Fälle großartig sein. Sie sind eine großartige Möglichkeit, bestimmte Ergebnisse aus Tabellen aus Tabellen zurückzugeben, die nicht einfach miteinander verbunden werden können - oder aus völlig unabhängigen Tabellen. Es gibt jedoch einige Regeln zu befolgen.
- Die Spaltentypen aus der ersten Abfrage müssen mit den Spaltentypen aus jeder anderen Abfrage unten übereinstimmen.
- Die Namen der Spalten aus der ersten Abfrage werden verwendet, um die gesamte Ergebnismenge zu identifizieren.
- Die Anzahl der Spalten in jeder Abfrage muss gleich sein.
Jetzt fragen Sie sich vielleicht , was der Unterschied zwischen der Verwendung von unionund ist union all. Eine unionAbfrage entfernt Duplikate, eine union allnicht. Dies bedeutet, dass es bei der Verwendung von unionover einen kleinen Leistungseinbruch gibt, union allaber die Ergebnisse können sich lohnen - ich werde jedoch nicht darüber spekulieren.
In diesem Zusammenhang sollten einige zusätzliche Hinweise erwähnt werden.
- Wenn wir die Ergebnisse bestellen wollten, können wir einen verwenden,
order byaber Sie können den Alias nicht mehr verwenden. In der obigen Abfrage order by a.IDwürde das Anhängen eines zu einem Fehler führen - was die Ergebnisse betrifft, wird die Spalte IDeher aufgerufen als a.ID- obwohl in beiden Abfragen derselbe Alias verwendet wurde.
- Wir können nur eine
order byAussage haben, und es muss die letzte sein.
Für die nächsten Beispiele füge ich unseren Tabellen einige zusätzliche Zeilen hinzu.
Ich habe Holdender Markentabelle hinzugefügt . Ich habe auch eine Zeile hinzugefügt cars, die den colorWert 12- hat und die keinen Bezug in der Farbtabelle hat.
Okay, der Chef ist wieder da und bellt Anfragen an - * Ich möchte eine Zählung jeder Marke, die wir führen, und der Anzahl der Autos darin! `- Typischerweise kommen wir nur zu einem interessanten Abschnitt unserer Diskussion und der Chef möchte mehr Arbeit .
Richtig, das erste, was wir tun müssen, ist eine vollständige Liste möglicher Marken zu erhalten.
select
a.brand
from
brands a
+--------+
| brand |
+--------+
| Ford |
| Toyota |
| Nissan |
| Smart |
| BMW |
| Holden |
+--------+
6 rows in set (0.00 sec)
Wenn wir dies nun mit unserem Autotisch verbinden, erhalten wir das folgende Ergebnis:
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)
Was natürlich ein Problem ist - wir sehen keine Erwähnung der schönen HoldenMarke, die ich hinzugefügt habe.
Dies liegt daran, dass ein Join in beiden Tabellen nach übereinstimmenden Zeilen sucht . Da in Fahrzeugen vom Typ keine Daten vorhanden sind, werden Holdendiese nicht zurückgegeben. Hier können wir einen outerJoin verwenden. Dadurch werden alle Ergebnisse einer Tabelle zurückgegeben, unabhängig davon, ob sie mit der anderen Tabelle übereinstimmen oder nicht:
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)
Jetzt, wo wir das haben, können wir eine schöne Aggregatfunktion hinzufügen, um eine Zählung zu erhalten und den Chef für einen Moment von unserem Rücken zu bekommen.
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)
Und damit schleicht sich der Chef weg.
Um dies näher zu erläutern, können äußere Verknüpfungen vom Typ leftoder sein right. Links oder rechts definiert, welche Tabelle vollständig enthalten ist. A left outer joinenthält alle Zeilen aus der Tabelle links, während (Sie haben es erraten) a right outer joinalle Ergebnisse aus der Tabelle rechts in die Ergebnisse einbringt.
Einige Datenbanken erlauben eine, full outer joindie Ergebnisse (ob übereinstimmend oder nicht) aus beiden Tabellen zurückbringt , dies wird jedoch nicht in allen Datenbanken unterstützt.
Nun, ich nehme an, zu diesem Zeitpunkt fragen Sie sich wahrscheinlich, ob Sie Join-Typen in einer Abfrage zusammenführen können oder nicht - und die Antwort lautet: Ja, das können Sie absolut.
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)
Warum sind das nicht die erwarteten Ergebnisse? Dies liegt daran, dass wir zwar die äußere Verknüpfung von Autos zu Marken ausgewählt haben, diese jedoch nicht in der Verknüpfung zu Farben angegeben wurde. Daher führt diese bestimmte Verknüpfung nur zu Ergebnissen, die in beiden Tabellen übereinstimmen.
Hier ist die Abfrage, die funktionieren würde, um die erwarteten Ergebnisse zu erzielen:
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)
Wie wir sehen können, haben wir zwei äußere Verknüpfungen in der Abfrage und die Ergebnisse kommen wie erwartet durch.
Wie wäre es nun mit den anderen Arten von Joins, die Sie fragen? Was ist mit Kreuzungen?
Nun, nicht alle Datenbanken unterstützen das, intersectionaber so ziemlich alle Datenbanken ermöglichen es Ihnen, eine Schnittmenge durch einen Join (oder zumindest eine gut strukturierte where-Anweisung) zu erstellen.
Ein Schnittpunkt ist eine Art von Verknüpfung, die einer unionwie oben beschrieben ähnelt. Der Unterschied besteht jedoch darin, dass nur Datenzeilen zurückgegeben werden, die zwischen den verschiedenen einzelnen Abfragen, die durch die Vereinigung verbunden sind, identisch sind (und ich meine identisch). Es werden nur Zeilen zurückgegeben, die in jeder Hinsicht identisch sind.
Ein einfaches Beispiel wäre als solches:
select
*
from
colors
where
ID>2
intersect
select
*
from
colors
where
id<4
Während eine normale unionAbfrage alle Zeilen der Tabelle zurückgeben würde (die erste Abfrage gibt etwas zurück ID>2und die zweite etwas ID<4), was zu einem vollständigen Satz führen würde, würde eine Schnittabfrage nur die Zeilenübereinstimmung zurückgeben, id=3da sie beide Kriterien erfüllt.
Wenn Ihre Datenbank eine intersectAbfrage nicht unterstützt , kann die oben genannte Abfrage problemlos mit der folgenden Abfrage ausgeführt werden:
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)
Wenn Sie eine Schnittmenge zwischen zwei verschiedenen Tabellen mithilfe einer Datenbank ausführen möchten, die von Natur aus keine Schnittpunktabfrage unterstützt, müssen Sie für jede Spalte der Tabellen einen Join erstellen .