Äußere Verbindungen in SQL (Äußere Verbindungen in SQL), Lektion, Seite 722984
https://www.purl.org/stefan_ram/pub/outer_joins_sql (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
SQL-Kurs

Äußere Verbindungen in SQL 

Beispiele und Erläuterungen

Bei einer äußeren Verbindung  wird das Ergebnis einer Verbindung um zusätzliche Zeilen  erweitert.

Die Bezeichnung „äußeren Verbindung“ könnte daher stammen, daß jene zusätzlichen Zeilen außerhalb  des Ergebnisses eines normalen Joins liegen.

Protokoll (Beginn)

WARNINGS; SET sql_mode = 'ANSI,TRADITIONAL';
DROP SCHEMA S; CREATE SCHEMA S; USE S;

CREATE TABLE L ( L VARCHAR( 255 ));
INSERT INTO L ( L ) VALUES ( 'I' );
INSERT INTO L ( L ) VALUES ( 'L' );

CREATE TABLE R ( R VARCHAR( 255 ));
INSERT INTO R ( R ) VALUES ( 'I' );
INSERT INTO R ( R ) VALUES ( 'R' );

Die linke Verbindung

Protokoll (Fortsetzung)

SELECT * FROM L INNER JOIN R ON L = R;

+------+------+
| L | R |
+------+------+
| I | I |
+------+------+

In der inneren Verbindung  sehen wir die Zeilen mit gleichen Werten in den beiden gleichgesetzten Spalten.

Protokoll (Fortsetzung)

SELECT * FROM L LEFT JOIN R ON L = R;

+------+------+
| L | R |
+------+------+
| I | I |
| L | NULL |
+------+------+

Die linke Verbindung  wurde um alle Zeilen der linken Seite  des Produkts (der Tabelle »L«) aus den angegebenen Spalten erweitert, die noch nicht mindestens einmal im inneren Produkt vorkommen. Eine solche linke Verbindung wird auch als „linke äußere  Verbindung“ bezeichnet.

Die linke Verbindung unter Ausschluß der inneren Verbindung

Durch eine Selektion  können wir gezielt anzeigen lassen, welche Zeilen der linken Tabelle nicht  im inneren Produkt vorkommen („welcher Mitarbeiter hat noch nie eine Schulung besucht?“).

Protokoll (Fortsetzung)

SELECT L FROM L LEFT JOIN R ON L = R WHERE R IS NULL;

+------+
| L |
+------+
| L |
+------+

Die rechte Verbindung

Die rechte Verbindung  wurde um alle Zeilen der rechten Seite  des Produkts (der Tabelle »R«) aus den angegebenen Spalten erweitert, die noch nicht mindestens einmal im inneren Produkt vorkommen. Eine solche rechte Verbindung wird auch als „rechte äußere  Verbindung“ bezeichnet.

Protokoll (Fortsetzung)

SELECT * FROM L RIGHT JOIN R ON L = R;

+------+------+
| L | R |
+------+------+
| I | I |
| NULL | R |
+------+------+

Die rechte Verbindung unter Ausschluß der inneren Verbindung

Durch eine Selektion  können wir gezielt anzeigen lassen, welche Zeilen der rechten Tabelle nicht  im inneren Produkt vorkommen („welche Schulung wurde noch nie von jemandem besucht?“).

Protokoll (Fortsetzung)

SELECT R FROM L RIGHT JOIN R ON L = R WHERE L IS NULL;

+------+
| R |
+------+
| R |
+------+

Die äußere Verbindung

Wir sehen linke und rechte Verbindungen als äußere Verbindungen an.

Unter „der äußeren Verbindung “ versteht man aber normalerweise die Vereinigung  von linker und rechter Verbindung.

Da es in MySQL keine spezielle Unterstützung für die Ermittlung der äußeren Verbindungen gibt, muß man sie dort durch eine Vereinigung einer linken mit einer rechten Verbindung nachbilden.

Protokoll (Fortsetzung)

SELECT * FROM L LEFT JOIN R ON L = R
UNION
SELECT * FROM L RIGHT JOIN R ON L = R;

+------+------+
| L | R |
+------+------+
| I | I |
| L | NULL |
| NULL | R |
+------+------+

Anforderungen

Bei einer äußeren Verbindung muß eine ON-Klausel angegeben werden.

Anwendungsbeispiele

Integrierte Darstellung von Erweiterungsdatensätzen

Im folgenden Beispiel gibt es eine Tabelle von Personen. Für diejenigen Personen, welche Angestellte sind, gibt es eine Erweiterungstabelle mit der Abteilungs- und Rufnummer.

Die linke Verbindung gestattet es uns, alle Personen zusammen mit etwaigen Erweiterungsdatensätzen anzuzeigen (siehe letzte abgeleitete Tabelle).

main.sql

WARNINGS; SET sql_mode = 'ANSI,TRADITIONAL';
DROP SCHEMA S; CREATE SCHEMA S; USE S;

CREATE TABLE PERSON ( PERSON VARCHAR( 255 ), VORNAME VARCHAR( 255 ), NACHNAME VARCHAR( 255 ));
INSERT INTO PERSON ( PERSON, VORNAME, NACHNAME )VALUES ( '0', 'Laura', 'Pfeiffer' );
INSERT INTO PERSON ( PERSON, VORNAME, NACHNAME )VALUES ( '1', 'Liam', 'Wolff' );
INSERT INTO PERSON ( PERSON, VORNAME, NACHNAME )VALUES ( '2', 'Lina', 'Arnold' );
INSERT INTO PERSON ( PERSON, VORNAME, NACHNAME )VALUES ( '3', 'Elias', 'Sauer' );
INSERT INTO PERSON ( PERSON, VORNAME, NACHNAME )VALUES ( '4', 'Levi', 'Vogr' );
INSERT INTO PERSON ( PERSON, VORNAME, NACHNAME )VALUES ( '5', 'Julia', 'Thomas' );

CREATE TABLE ANGESTELLTER ( PERSON VARCHAR( 255 ), ABTEILUNG VARCHAR( 255 ), RUFNUMMER VARCHAR( 255 ));
INSERT INTO ANGESTELLTER ( PERSON, ABTEILUNG, RUFNUMMER ) VALUES ( '0', 'I', '5631' );
INSERT INTO ANGESTELLTER ( PERSON, ABTEILUNG, RUFNUMMER ) VALUES ( '2', 'I', '4312' );
INSERT INTO ANGESTELLTER ( PERSON, ABTEILUNG, RUFNUMMER ) VALUES ( '3', 'II', '8491' );
INSERT INTO ANGESTELLTER ( PERSON, ABTEILUNG, RUFNUMMER ) VALUES ( '5', 'IV', '6112' );

SELECT PERSON, VORNAME, NACHNAME FROM PERSON;

SELECT PERSON, ABTEILUNG, RUFNUMMER FROM ANGESTELLTER;

SELECT PERSON.PERSON AS PERSON, VORNAME, NACHNAME, ABTEILUNG, RUFNUMMER FROM PERSON INNER JOIN ANGESTELLTER ON PERSON.PERSON = ANGESTELLTER.PERSON;

SELECT PERSON.PERSON AS PERSON, VORNAME, NACHNAME, ABTEILUNG, RUFNUMMER FROM PERSON LEFT JOIN ANGESTELLTER ON PERSON.PERSON = ANGESTELLTER.PERSON;

Protokoll
+--------+---------+----------+
| PERSON | VORNAME | NACHNAME |
+--------+---------+----------+
| 0 | Laura | Pfeiffer |
| 1 | Liam | Wolff |
| 2 | Lina | Arnold |
| 3 | Elias | Sauer |
| 4 | Levi | Vogr |
| 5 | Julia | Thomas |
+--------+---------+----------+
+--------+-----------+-----------+
| PERSON | ABTEILUNG | RUFNUMMER |
+--------+-----------+-----------+
| 0 | I | 5631 |
| 2 | I | 4312 |
| 3 | II | 8491 |
| 5 | IV | 6112 |
+--------+-----------+-----------+
+--------+---------+----------+-----------+-----------+
| PERSON | VORNAME | NACHNAME | ABTEILUNG | RUFNUMMER |
+--------+---------+----------+-----------+-----------+
| 0 | Laura | Pfeiffer | I | 5631 |
| 2 | Lina | Arnold | I | 4312 |
| 3 | Elias | Sauer | II | 8491 |
| 5 | Julia | Thomas | IV | 6112 |
+--------+---------+----------+-----------+-----------+
+--------+---------+----------+-----------+-----------+
| PERSON | VORNAME | NACHNAME | ABTEILUNG | RUFNUMMER |
+--------+---------+----------+-----------+-----------+
| 0 | Laura | Pfeiffer | I | 5631 |
| 2 | Lina | Arnold | I | 4312 |
| 3 | Elias | Sauer | II | 8491 |
| 5 | Julia | Thomas | IV | 6112 |
| 1 | Liam | Wolff | NULL | NULL |
| 4 | Levi | Vogr | NULL | NULL |
+--------+---------+----------+-----------+-----------+

Artikel ohne Stammdatensatz

Solche äußeren Verbindungen werden oft verwendet, um das Fehlen oder Nichtvorkommen eines Eintrags zu entdecken.

Das folgende Beispiel zeigt die Ermittlung neuer Datensätze, zu deren Artikelnummern es noch keinen Stammdatensatz gibt.

main.sql

WARNINGS; SET sql_mode = 'ANSI,TRADITIONAL';
DROP SCHEMA S; CREATE SCHEMA S; USE S;

CREATE TABLE STAMMDATEN ( ARTIKEL VARCHAR( 255 ), NAME VARCHAR( 255 ), INFO VARCHAR( 255 ));
INSERT INTO STAMMDATEN ( ARTIKEL, NAME, INFO )VALUES ( '1', 'A', 'Haendische Info A' );
INSERT INTO STAMMDATEN ( ARTIKEL, NAME, INFO )VALUES ( '2', 'B', 'Haendische Info B' );
INSERT INTO STAMMDATEN ( ARTIKEL, NAME, INFO )VALUES ( '3', 'C', 'Haendische Info C' );

CREATE TABLE NEUDATEN ( ARTIKEL VARCHAR( 255 ), NAME VARCHAR( 255 ));
INSERT INTO NEUDATEN ( ARTIKEL, NAME ) VALUES ( '1', 'A' );
INSERT INTO NEUDATEN ( ARTIKEL, NAME ) VALUES ( '4', 'D' );

SELECT NEUDATEN.ARTIKEL FROM NEUDATEN LEFT JOIN STAMMDATEN
ON NEUDATEN.ARTIKEL = STAMMDATEN.ARTIKEL WHERE STAMMDATEN.ARTIKEL IS NULL;

Protokoll
+---------+
| ARTIKEL |
+---------+
| 4 |
+---------+

Übungsaufgaben

/   Tabellen anlegen und abfragen

Lassen Sie diejenigen Zeilen aus dem äußeren Produkt von »L« und »R« anzeigen, die mindestens in einer Spalte des äußeren Produkts »NULL« enthalten (also die äußere Verbindung unter Ausschluß der inneren Verbindung).

Skript

WARNINGS; SET sql_mode = 'ANSI,TRADITIONAL';
DROP SCHEMA S; CREATE SCHEMA S; USE S;

CREATE TABLE L ( L VARCHAR( 255 ));
INSERT INTO L ( L ) VALUES ( 'I' );
INSERT INTO L ( L ) VALUES ( 'L' );

CREATE TABLE R ( R VARCHAR( 255 ));
INSERT INTO R ( R ) VALUES ( 'I' );
INSERT INTO R ( R ) VALUES ( 'R' );

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram722984 stefan_ram:722984 Äußere Verbindungen in SQL Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722984, slrprddef722984, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/outer_joins_sql