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 model
Spalte der cars
Tabelle auf die models
Spalte der cars
Tabelle, die wir haben. Jetzt wissen wir, dass die Modelltabelle eine ID von 1
für hat, Sports
also 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_DEPARTMENT
wü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=1
oder 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 cars
die 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, from
verknü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 join
Anweisung einfügen möchten , ist hier ein Beispiel. Wenn die models
Tabelle markenspezifische Modelle und daher auch eine Spalte mit dem Namen hat, brand
die mit der brands
Tabelle auf dem ID
Feld 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 cars
Haupttabelle 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 ID
von cars
und dem model
von 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 union
Abfrage 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 all
Klausel 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 union
Abfragen 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 union
und ist union all
. Eine union
Abfrage entfernt Duplikate, eine union all
nicht. Dies bedeutet, dass es bei der Verwendung von union
over einen kleinen Leistungseinbruch gibt, union all
aber 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 by
aber Sie können den Alias nicht mehr verwenden. In der obigen Abfrage order by a.ID
würde das Anhängen eines zu einem Fehler führen - was die Ergebnisse betrifft, wird die Spalte ID
eher aufgerufen als a.ID
- obwohl in beiden Abfragen derselbe Alias verwendet wurde.
- Wir können nur eine
order by
Aussage 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 Holden
der Markentabelle hinzugefügt . Ich habe auch eine Zeile hinzugefügt cars
, die den color
Wert 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 Holden
Marke, 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 Holden
diese nicht zurückgegeben. Hier können wir einen outer
Join 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 left
oder sein right
. Links oder rechts definiert, welche Tabelle vollständig enthalten ist. A left outer join
enthält alle Zeilen aus der Tabelle links, während (Sie haben es erraten) a right outer join
alle Ergebnisse aus der Tabelle rechts in die Ergebnisse einbringt.
Einige Datenbanken erlauben eine, full outer join
die 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, intersection
aber 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 union
wie 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 union
Abfrage alle Zeilen der Tabelle zurückgeben würde (die erste Abfrage gibt etwas zurück ID>2
und 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=3
da sie beide Kriterien erfüllt.
Wenn Ihre Datenbank eine intersect
Abfrage 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 .