SQL: INNER JOIN über 3 Tabellen

Hier ein Beispiel wie man einen INNER JOIN über 3 Tabellen macht.
Getestet ist das Beispiel mit MySQL 5.1 und SQLite 3.

Ich habe hier 3 Tabellen (Adressen, Rechnungen und RechnungsPosten) welche ich mit folgendem SQL Query erstellen lasse:
Achtung: SQLite 3 Version (MySQL Version weiter unten)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
CREATE TABLE [Adressen] (
  [id] INTEGER NOT NULL PRIMARY KEY,
  [vorname] VARCHAR(50),
  [name] VARCHAR(50),
  [email] VARCHAR(100)
  );
 
INSERT INTO Adressen (vorname,name,email) VALUES ('Karl','Einzer','karl@einzer.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Helmut','Zweier','helmut@zweier.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Paul','Dreier','paul@dreier.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Egon','Vierer','egon@vierer.de');
 
CREATE TABLE [Rechnungen] (
  [id] INTEGER NOT NULL PRIMARY KEY,
  [kundennr] VARCHAR(4),
  [rgnr] VARCHAR(50),
  [rgdatum] VARCHAR(8),
  [bezahlt] VARCHAR(1)
  );
 
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('1','1000','20120601','1');
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('1','1001','20120610','1');
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('3','1002','20120612','0');
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('4','1003','20120612','0');
 
CREATE TABLE [RechnungsPosten] (
  [id] INTEGER NOT NULL PRIMARY KEY,
  [rgnr] VARCHAR(50),
  [bezeichnung] VARCHAR(50),
  [preis] VARCHAR(4)
  );
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1000','Malstifte','10');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1000','Malpapier','15');
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1001','Gummibärchen','2');
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1002','Notebook (toll)','400');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1002','Maus (grau)','15');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1002','1000 GB Externe HDD 3,5','70');
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Holzplatten','30');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Spaxschrauben','5');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Gitterdraht','14');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Fuchsschwanz','16');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Drahtschere','9');

Und hier die MySQL Version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
CREATE TABLE Adressen (
  id INT(11) NOT NULL AUTO_INCREMENT,
  vorname VARCHAR(50) DEFAULT NULL,
  name VARCHAR(50) DEFAULT NULL,
  email VARCHAR(100) DEFAULT NULL,
  PRIMARY KEY (id)
  );
 
INSERT INTO Adressen (vorname,name,email) VALUES ('Karl','Einzer','karl@einzer.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Helmut','Zweier','helmut@zweier.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Paul','Dreier','paul@dreier.de');
INSERT INTO Adressen (vorname,name,email) VALUES ('Egon','Vierer','egon@vierer.de');
 
CREATE TABLE Rechnungen (
  id INT(11) NOT NULL AUTO_INCREMENT,
  kundennr VARCHAR(4) DEFAULT NULL,
  rgnr VARCHAR(50) DEFAULT NULL,
  rgdatum VARCHAR(8) DEFAULT NULL,
  bezahlt VARCHAR(1) DEFAULT NULL,
  PRIMARY KEY (id)
  );
 
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('1','1000','20120601','1');
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('1','1001','20120610','1');
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('3','1002','20120612','0');
INSERT INTO Rechnungen (kundennr,rgnr,rgdatum,bezahlt) VALUES ('4','1003','20120612','0');
 
CREATE TABLE RechnungsPosten (
  id INT(11) NOT NULL AUTO_INCREMENT,
  rgnr VARCHAR(50) DEFAULT NULL,
  bezeichnung VARCHAR(50) DEFAULT NULL,
  preis VARCHAR(4) DEFAULT NULL,
  PRIMARY KEY (id)
  );
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1000','Malstifte','10');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1000','Malpapier','15');
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1001','Gummibärchen','2');
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1002','Notebook (toll)','400');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1002','Maus (grau)','15');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1002','1000 GB Externe HDD 3,5','70');
 
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Holzplatten','30');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Spaxschrauben','5');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Gitterdraht','14');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Fuchsschwanz','16');
INSERT INTO RechnungsPosten (rgnr,bezeichnung,preis) VALUES ('1003','Drahtschere','9');

Aus diesen Daten möchte ich nun alle Rechnungen mit Rechnungsposten und Kunden-infos haben (sollte jetzt nichts ungewöhnliches sein).

SQL Query OHNE JOIN
Ohne einen JOIN würde ich die Tabellen direkt anhand der ID´s in der WHERE Bedingung verknüpfen:

1
2
3
4
5
6
7
8
9
SELECT 
* 
FROM 
     Adressen,
     Rechnungen,
     RechnungsPosten
WHERE
     (Adressen.id = Rechnungen.kundennr AND     
     Rechnungen.rgnr = RechnungsPosten.rgnr)

Bzw würde ich das Ergebnis etwas einschränken und den Tabellen-Spalten evtl. Sprechendere Namen geben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT 
     r.id AS DatensatzID,     
     r.rgnr AS RechnungsNummer,
     k.vorname AS Vorname,
     k.name AS Nachname,
     rp.bezeichnung AS Bezeichnung,
     rp.preis AS Preis,   
     r.rgdatum AS RechnungsDatum,
     r.bezahlt AS Bezahlt
FROM 
     Adressen AS k,
     Rechnungen AS r,
     RechnungsPosten AS rp
WHERE
     (k.id = r.kundennr AND     
     r.rgnr = rp.rgnr)

Heraus kommt dann diese Tabelle:

RecNo DatensatzID RechnungsNummer Vorname Nachname Bezeichnung             Preis RechnungsDatum Bezahlt 
----- ----------- --------------- ------- -------- ----------------------- ----- -------------- ------- 
    1           1 1000            Karl    Einzer   Malpapier               15    20120601       1       
    2           1 1000            Karl    Einzer   Malstifte               10    20120601       1       
    3           2 1001            Karl    Einzer   Gummibärchen            2     20120610       1       
    4           3 1002            Paul    Dreier   1000 GB Externe HDD 3,5 70    20120612       0       
    5           3 1002            Paul    Dreier   Maus (grau)             15    20120612       0       
    6           3 1002            Paul    Dreier   Notebook (toll)         400   20120612       0       
    7           4 1003            Egon    Vierer   Drahtschere             9     20120612       0       
    8           4 1003            Egon    Vierer   Fuchsschwanz            16    20120612       0       
    9           4 1003            Egon    Vierer   Gitterdraht             14    20120612       0       
   10           4 1003            Egon    Vierer   Holzplatten             30    20120612       0       
   11           4 1003            Egon    Vierer   Spaxschrauben           5     20120612       0       

Und hier, wie oben schon eingeleitet der SQL Query mit einem INNER JOIN über diese 3 Tabellen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SELECT 
     r.id AS DatensatzID,     
     r.rgnr AS RechnungsNummer,
     k.vorname AS Vorname,
     k.name AS Nachname,
     rp.bezeichnung AS Bezeichnung,
     rp.preis AS Preis,   
     r.rgdatum AS RechnungsDatum,
     r.bezahlt AS Bezahlt
FROM 
     ( Adressen AS k    
       INNER JOIN     
       Rechnungen AS r    
       ON     
       k.id = r.kundennr
     )
     INNER JOIN 
     RechnungsPosten AS rp     
     ON     
     r.rgnr = rp.rgnr

Als Ergebnis kommt die selbe Tabelle wie oben heraus.
Ob die Benutzung des JOIN jetzt Performace-Technische Vorteile gegenüber dem direkten verknüpfen der Tabellen anhand der ID´s hat ist mir nicht bekannt – ich konnte es aber mit den wenigen Daten die ich hier habe nicht weiter probieren.
Auf jeden fall fällt in der JOIN-Variante der gesamte WHERE Teil weg, was den Query insgesamt etwas übersichtlicher macht.

leave your comment


*

Unterstütze den Frickelblog!