# INNER JOIN: Definition und Anwendung

Abfragen über mehrere Datenbanktabellen realisieren Sie im [relationalen Datenbankmodell](https://www.ionos.at/digitalguide/hosting/hosting-technik/relationale-datenbanken/ "Relationale Datenbanken") mithilfe von [SQL-JOINs](https://www.ionos.at/digitalguide/hosting/hosting-technik/sql-join/ "SQL-JOIN"). Bei allen JOIN-Typen mit Ausnahme des CROSS-JOINs handelt es sich um eine Kombination aus kartesischem Produkt und Selektion.

Das [Datenbank-Managementsystem (DBMS)](https://www.ionos.at/digitalguide/hosting/hosting-technik/datenbankmanagementsystem-dbms-erklaert/ "Datenbankmanagementsystem (DBMS) erklärt") bildet zunächst das **Kreuzprodukt** zweier Datenbanktabellen. Anschließend filtert es das Ergebnis gemäß einer vom Anwender via SQL-Statement definierten **Selektionsbedingung**. Der INNER JOIN hebt sich dabei von allen anderen JOIN-Typen durch eine **minimale Ergebnismenge** ab. Als Ergebnis eines INNER JOINs werden lediglich die Datensätze des Kreuzproduktes ausgegeben, die die Selektionsbedingung erfüllen. Das Resultat ist eine Ergebnistabelle (ein *View*) ohne Nullwerte.

## INNER JOINs in der Praxis

Wir verdeutlichen den INNER JOIN an einem Beispiel und gehen dabei von zwei Tabellen aus. In der Tabelle „mitarbeiter“ sind die Mitarbeiter eines Unternehmens inklusive Mitarbeiter-ID (*m\_id*) und zugehöriger Abteilung (*a\_id*) erfasst.

**Tabelle: mitarbeiter**

<table>
  <thead>
    <tr>
      <th>m\_id</th>
      <th>nachname</th>
      <th>vorname</th>
      <th>a\_id</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Schmidt</td>
      <td>Udo</td>
      <td>3</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Müller</td>
      <td>Wolfgang</td>
      <td>1</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Meyer</td>
      <td>Günther</td>
      <td>1</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Krause</td>
      <td>Helmut</td>
      <td>2</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Schneider</td>
      <td>Kevin</td>
      <td>NULL</td>
    </tr>
  </tbody>
</table>

Die Tabelle zeigt zwei Besonderheiten: Die Mitarbeiter Müller und Meyer arbeiten in derselben Abteilung. Der Mitarbeiter Schneider wurde bisher noch keiner Abteilung zugeordnet.

Die Tabelle „abteilungen“ listet alle Abteilungen des Unternehmens inklusive ID und Standortangabe auf.

**Tabelle: abteilungen**

<table>
  <thead>
    <tr>
      <th>a\_id</th>
      <th>bezeichnung</th>
      <th>standort</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Vertrieb</td>
      <td>Frankfurt</td>
    </tr>
    <tr>
      <td>2</td>
      <td>IT</td>
      <td>Bad Homburg</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Personal</td>
      <td>Offenbach</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Forschung</td>
      <td>Bad Homburg</td>
    </tr>
  </tbody>
</table>

Beide Tabellen sind über eine **Fremdschlüsselbeziehung** miteinander verknüpft. Die Abteilungs-ID, die in der Tabelle „abteilungen“ als Primärschlüssel fungiert, wurde in die Tabelle „mitarbeiter“ als Fremdschlüssel integriert.

Diese Verknüpfung ermöglicht uns einen INNER JOIN über beide Tabellen. Ein solcher ist beispielsweise notwendig, um zu ermitteln, welcher Mitarbeiter an welchem Standort tätig ist.

Bei Abfragen relationaler Datenbanken wird in der Regel eine **Entsprechung von Primär- und Fremdschlüssel als Selektionsbedingung** definiert. Die Bedingung gilt als erfüllt, wenn der ausgewählte Fremdschlüssel der einen Tabelle mit dem Primärschlüssel der anderen Tabelle übereinstimmt (=). Es werden somit nur die Datensätze ausgegeben, die gemeinsame Werte enthalten.

Ein solcher INNER JOIN wird in der **relationalen Algebra** folgendermaßen notiert.

mitarbeiter⋈a\_id=a\_idabteilungen

Relationale Datenbanksysteme nehmen Befehle allerdings nicht in der Syntax der relationalen Algebra entgegen, sondern in Form von **SQL-Statements**.

```none
SELECT * FROM mitarbeiter INNER JOIN abteilungen ON mitarbeiter.a_id = abteilungen.a_id;
```

Der **Befehl SELECT** weist das DBMS an, Daten aus der Datenbank abzufragen. Alternativ bietet SQL die Möglichkeit, Daten einzutragen (INSERT INTO), zu ändern (UPDATE) oder zu löschen (DELETE FROM). Auf den Befehl SELECT folgt die Angabe, welche Daten abgerufen werden sollen. Da wir den kompletten Datensatz abrufen möchten, wählen wir einen entsprechenden Platzhalter: den Asterisk (\*).

Der Befehl SELECT erfordert in jedem Fall das **Keyword FROM** sowie die Angabe, aus welcher Tabelle bzw. aus welchem Tabellenverbund (JOIN) die Daten abgerufen werden sollen. In unserem Fall ist die Datenquelle ein INNER JOIN über die Tabellen „abteilungen“ und „mitarbeiter“. Zudem geben wir mit dem **Schlüsselwort ON** eine Bedingung für die Verknüpfung an. Wir möchten lediglich die Datensätze verknüpfen und als Ergebnistabelle ausgeben lassen, bei denen die *a\_id* der Tabelle „mitarbeiter“ der *a\_id* der Tabelle „abteilungen“ entspricht.

Tipp Da der INNER JOIN der wichtigste SQL-JOIN ist, können Sie das Schlüsselwort „INNER“ bei Bedarf auch weglassen.

Ein INNER JOIN über die beiden Ausgangstabellen mit der Bedingung *mitarbeiter.a\_id = abteilungen.a\_id* liefert folgende Ergebnistabelle.

**Tabelle: SQL INNER JOIN über „mitarbeiter“ und „abteilungen“**

<table>
  <thead>
    <tr>
      <th>m\_id</th>
      <th>nachname</th>
      <th>vorname</th>
      <th>mitarbeiter.a\_id</th>
      <th>abteilungen.a\_id</th>
      <th>bezeichnung</th>
      <th>standort</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Schmidt</td>
      <td>Udo</td>
      <td>3</td>
      <td>3</td>
      <td>Personal</td>
      <td>Offenbach</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Müller</td>
      <td>Wolfgang</td>
      <td>1</td>
      <td>1</td>
      <td>Vertrieb</td>
      <td>Frankfurt</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Meyer</td>
      <td>Günther</td>
      <td>1</td>
      <td>1</td>
      <td>Vertrieb</td>
      <td>Frankfurt</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Krause</td>
      <td>Helmut</td>
      <td>2</td>
      <td>2</td>
      <td>IT</td>
      <td>Bad Homburg</td>
    </tr>
  </tbody>
</table>

Vergleicht man die Ergebnistabelle mit den beiden Ausgangstabellen, fällt auf, dass jeweils ein Datensatz aus jeder Tabelle fehlt. Und zwar die Datensätze für deren Wert in der Spalte *a\_id* keine Entsprechung in der jeweils anderen Tabelle vorhanden ist.

```none
(5, Schneider, Kevin, NULL)
```

und

```none
(4, Forschung, Bad Homburg)
```

Dem Mitarbeiter Schneider wurde noch keine Abteilung zugewiesen. Der Abteilung Forschung wurden noch keine Mitarbeiter zugewiesen. Beide Datensätze werden bei einem INNER JOIN, der der Gegenüberstellung von Mitarbeitern zu ihren jeweiligen Abteilungen dient, ausgeblendet. Möchten wir hingegen genau solche Unregelmäßigkeiten ermitteln und im Rahmen der Abfrage sichtbar machen, sollten wir statt eines INNER JOINs einen [OUTER JOIN](https://www.ionos.at/digitalguide/hosting/hosting-technik/sql-outer-join/) wählen.

[![Bild: Schematische Darstellung eines INNER JOINs als Mengendiagramm](https://www.ionos.at/digitalguide/fileadmin/_processed_/a/6/csm_innerjoin_61f561eeb7.webp "Schematische Darstellung eines INNER JOINs als Mengendiagramm")](https://www.ionos.at/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/innerjoin.png) Schematische Darstellung eines INNER JOINs als Mengendiagramm ## Unterarten des INNER JOINs

INNER JOINs lassen sich als THETA JOINs, EQUI JOINs, NON EQUI JOINs und NATURAL JOINs realisieren.

### THETA JOINs, EQUI JOINs und NON EQUI JOINs

Der INNER JOIN der SQL-Terminologie entspricht dem **THETA JOIN** der relationalen Algebra. Der THETA JOIN grenzt sich von EQUI JOINs und NON EQUI JOINs dadurch ab, dass er Anwendern einen uneingeschränkten Satz an Vergleichsoperatoren zur Auswahl stellt. **EQUI JOINs** hingegen schränken die Selektionsbedingung bei Abfragen auf die Gleichheit von Spaltenwerten ein. Bei **NON EQUI JOINs** wiederum sind alle Vergleichsoperatoren mit Ausnahme des Gleichheitszeichens erlaubt.

<table>
  <thead>
    <tr>
      <th>JOIN-Typ</th>
      <th>Erlaubte Vergleichsoperatoren</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>THETA JOIN</td>
      <td>= (gleich) &lt; (kleiner als) &gt; (größer als)≤ (kleiner oder gleich)≥ (größer oder gleich)&lt;&gt; (ungleich)!= (ungleich)</td>
    </tr>
    <tr>
      <td>EQUI JOIN</td>
      <td>= (gleich)</td>
    </tr>
    <tr>
      <td>NON EQUI JOIN</td>
      <td>&lt; (kleiner als) &gt; (größer als)≤ (kleiner oder gleich)≥ (größer oder gleich)&lt;&gt; (ungleich)!= (ungleich)</td>
    </tr>
  </tbody>
</table>

### NATURAL JOINs

Werden zwei Tabellen (wie in den vorangehenden Beispielen) über gleichnamige Spalten verbunden, werden INNER JOINs in der Regel als **NATURAL JOINs** umgesetzt.

Bei NATURAL JOINs handelt es sich um eine Unterart des EQUI JOINs. Wie der EQUI JOIN setzt auch der NATURAL JOIN die Gleichheit zweier Spalten-Werte als Selektionsbedingung voraus.

Ein NATURAL INNER JOIN über die Tabellen „mitarbeiter und „abteilungen“ ließe sich beispielsweise folgendermaßen realisieren:

```none
SELECT * FROM mitarbeiter INNER JOIN abteilungen USING(a_id);
```

Das SQL-Statement weist das DBMS an, die aufgeführten Tabellen zu verbinden. Die Selektionsbedingung wird mithilfe des Schlüsselworts USING realisiert, das angibt, welche Spalten auf Gleichheit geprüft werden sollen. Voraussetzung ist, dass in beiden Tabellen eine Spalte *a\_id* existiert. Datensätze beider Tabellen werden nur dann in die Ergebnismenge aufgenommen, wenn das DBMS identische Werte in den mit *a\_id* bezeichneten Spalten vorfindet.

Auch die Ergebnistabelle des NATURAL JOINs unterscheidet sich von der des klassischen INNER JOINs dadurch, dass gleichnamige Spalten der Ausgangstabellen nicht doppelt aufgelistet, sondern zu einer gemeinsamen Spalte zusammengeführt werden.

**Tabelle: NATURAL JOIN über „mitarbeiter“ und „abteilungen“**

<table>
  <thead>
    <tr>
      <th>m\_id</th>
      <th>nachname</th>
      <th>vorname</th>
      <th>a\_id</th>
      <th>bezeichnung</th>
      <th>standort</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Schmidt</td>
      <td>Udo</td>
      <td>3</td>
      <td>Personal</td>
      <td>Offenbach</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Müller</td>
      <td>Wolfgang</td>
      <td>1</td>
      <td>Vertrieb</td>
      <td>Frankfurt</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Meyer</td>
      <td>Günther</td>
      <td>1</td>
      <td>Vertrieb</td>
      <td>Frankfurt</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Krause</td>
      <td>Helmut</td>
      <td>2</td>
      <td>IT</td>
      <td>Bad Homburg</td>
    </tr>
  </tbody>
</table>

Statt die *Abteilungs-IDs* beider Tabellen als *mitarbeiter.a\_id* und *abteilungen.a\_id* doppelt aufzuführen, wird lediglich eine Spalte *a\_id* ausgespielt.

Für NATURAL JOINs steht eine Kurzschreibweise zur Verfügung, die ohne USING-Klausel auskommt. Stattdessen verwendet man den Operator NATURAL JOIN. Die Kurzschreibweise der oben aufgeführten Operation entspricht folgendem SQL-Statement.

```none
SELECT * FROM mitarbeiter NATURAL JOIN abteilungen;
```

Der Operator NATURAL JOIN verbindet Tabellen automatisch über gleichnamige Spalten. Die Selektionsbedingung muss somit nicht explizit definiert werden.

Hinweis Ein NATURAL JOIN wird automatisch als INNER JOIN umgesetzt. Möchten Sie hingegen einen OUTER JOIN als NATURAL JOIN umsetzen, sind zusätzliche Schlüsselwörter erforderlich (beispielsweise NATURAL LEFT OUTER JOIN).


This is a markdown version of: [https://www.ionos.at/digitalguide/hosting/hosting-technik/inner-join-erklaerung-und-beispiele/](https://www.ionos.at/digitalguide/hosting/hosting-technik/inner-join-erklaerung-und-beispiele/) for AI/LLM consumption.