Was sind eigentlich SQL JOINS?

SQL JOINS bieten die Möglichkeit in relationalen Datenbanken, wie MySQL oder MS SQL Server, die Daten in den verschiedenen Tabellen sinnvoll zu verbinden. Wir nutzen in unserem Beispiel Code die MySQL Syntax, allerdings gibt es JOINS wie erwähnt in allen gängigen relationalen Datenbank Systemen, mit geringfügig abweichender Syntax.
Ich beschreibe das Konzept (und damit auch die grundlegende Funktionsweise von relationalen Datenbanken), am Beispiel eines Todo-Listen Projekts.

Was man vorher wissen sollte

Tabellen in relationalen Datenbank sind über Schlüssel verbunden. Schlüssel sind eindeutige (meist numerische) Datenbankfelder, die dem Datenbanksystem mitteilen, welche Daten in den verschiedenen Tabellen zusammengehören.

Primärschlüssel und Fremdschlüssel

Der Primärschlüssel ist eine eindeutige (meist numerische) Kennzeichnung eines Datensatzes (also einer Tabellenzeile) in einer Datenbanktabelle.

Beziehungen

Je nachdem wie die Tabellen und deren Schlüssel strukturiert sind, gibt es verschiedene Arten von Beziehungen. Um JOINS rein funktional zu erklären, ist diese Information nicht unbedingt notwendig, trägt aber meiner Ansicht nach zum Verständnis bei.

1:N Beziehung

In unserem ToDo Listen Projekt würde sich die 1:N Beziehung in den folgenden Tabellen und Feldern wiederspiegeln:

Tabelle: todolist

FeldnameDatentypBemerkungen
idintPrimärschlüssel
namevarchar(255)

Tabelle: todolist_item

FeldnameDatentypBemerkungen
idintPrimärschlüssel
textvarchar(255)
todolist_idintFremdschlüssel, der auf eine id aus der Tabelle todolist verweist

Der Fremdschlüssel ist die Verknüpfung zwischen den Daten in den verschiedenen Tabellen.
1:N (hier todolist:todolist_item) bedeutet in diesem Beispiel, dass ein Todo-Punkt oder ein Todolisten-Element zu genau einer Todoliste gehört.

M:N Beziehung

Möchte man, aber das man Todos in mehreren Listen anzeigen kann, braucht man eine M:N Beziehung. Hier kommt eine 3. Tabelle hinzu, die dies ermöglicht. Hier die modifizierte Datenbankstruktur:

Tabelle: todolist

FeldnameDatentypBemerkungen
idintPrimärschlüssel
namevarchar(255)

Tabelle: todolist_todoitem

FeldnameDatentypBemerkungen
todolist_idintFremdschlüssel, der auf eine id aus der Tabelle todolist verweist
todoitem_idintFremdschlüssel, der auf eine id aus der Tabelle todolist_item verweist

Tabelle: todolist_item

FeldnameDatentypBemerkungen
idintPrimärschlüssel
textvarchar(255)

In der Todo-Punkte Tabelle ist nun der Verweis auf die Todo-Liste weggefallen und in die Tabelle todolist_todoitem gewandert, die nun die Todo-Listen und die Todos verbindet.
Diese M:N Beziehung heißt, dass ein Todo zu beliebig vielen Todolisten gehören kann und umgekehrt.
Es gibt noch Variationen und Sonderfälle dieser Beziehung, da das aber nicht unser Hauptthema ist, lassen wir es an dieser Stelle dabei.

Es ist also beim Erstellen einer Datenbank im Vorfeld extrem wichtig, zu wissen wie die verschiedenen Einzelteile eines Projekts miteinander zusammenhängen. M:N ist nicht verboten, sollte dabei aber möglichst vermieden werden. Ziel ist immer, eine Beziehung so genau wie möglich abzubilden und damit unter anderem Datendopplungen zu vermeiden. Je genauer die Beziehungen abgebildet werden, desto einfacher und sicherer wird es nachher, wenn die Tabellen mit konkreten Daten gefüllt werden.

JOINS

Nun zu den JOINS. Sie sind die Werkzeuge, die uns das Datenbanksystem mit der Sprache SQL an die Hand gibt, um die Daten (die in den verschiedenen Tabellen verteilt sind) wieder sinnvoll zusammenzubringen.
Die folgenden Erklärungen behandeln nur die Grundlagen für JOINS. Hier gilt, wie bei den Beziehungen auch, dass es je nach Datenbanksystem hier noch Variationen und Sonderfunktionen gibt.
Es gibt im Grunde 2 Arten von JOINS:

INNER JOINS:
Der Standard, mit dem sich die Daten die zusammengehören verbinden lassen.
OUTER JOINS:
Manchmal kommt es vor, dass man von einer der verbunden Tabellen gerne zusätzlich die Daten hätte, die bei einem INNER JOIN nicht einbezogen worden wären, die also in der zweiten Tabelle kein passendes Gegenstück haben.
Hier wird es später noch auf die Begriffe links und rechts ankommen, da es einen LEFT OUTER JOIN und einen RIGHT OUTER JOIN gibt. Was so viel bedeutet wie: „Gib mir zusätzlich die Daten aus der linken (oder rechten) Tabelle, die in der jeweils anderen Tabelle kein Gegenstück (keinen passenden Datensatz) haben.

INNER JOIN

Ein MySQL INNER JOIN würde in unserem Todo Beispiel mit 1:N Beziehung folgendermaßen aussehen:

SELECT *
FROM todolist
JOIN todolist_item ON todolist.id = todolist_item.todolist_id;

Heraus kommt das folgende Ergebnis: Die Todos mit ihren Todo-Listen.

Das SQL Statement sagt aus:
„Verbinde die Totolisten sinnvoll mit den dazugehörigen Todos und gib mir alle Spalten der verbundenen Tabellen“.
Also: „Gib mir die Todo-Listen, mit den dazugehörigen Todos.“
Hier könnte man jetzt noch ein oder mehrere Bedingungen anfügen, z.B. wenn man nur die Todos von zwei bestimmten Listen wollte:

SELECT *
FROM todolist
JOIN todolist_item ON todolist.id = todolist_item.todolist_id
WHERE todolist.id = 4 OR todolist.id = 5;

In einer M:N Beziehung müsste man eine weitere JOIN Zeile einfügen, da man erst todolist mit der Verbindungstabelle todolist_todoitem verbinden und diese dann mit der Tabelle todolist_item verbinden müsste.

OUTER JOIN

Wenn ich die Todolisten mit den dazugehörigen Todos erhalte, fehlen bei einem INNER JOIN, die Todolisten, die KEINE Todos haben. Wenn ich trotzdem alle Todolisten sehen möchte (auch die
leeren), muss ich einen OUTER JOIN bemühen.
Wenn wir uns vorstellen, dass auf einem Blatt Papier die Todolisten-Tabelle links steht (FROM) und die Todo-Elemente Tabelle rechts (JOIN), brauchen wir hier einen LEFT OUTER JOIN:

SELECT *
FROM todolist
LEFT JOIN todolist_item ON todolist.id = todolist_item.todolist_id;

Hier erhalten wir in der Ergebnismenge einen Eintrag mehr: Die Todoliste „Test“ ohne Todos.

Wollten wir das gewünschte Ergebnis mit einem RIGHT JOIN realisieren, müssten wir die Tabellen in
FROM (linke Seite) und die Tabelle in JOIN (rechte) im SQL-Statement vertauschen:

SELECT *
FROM todolist_item
RIGHT JOIN todolist ON todolist.id = todolist_item.todolist_id;

Da hier wirklich nur grundsätzliches besprochen werden sollte, endet der Beitrag hier. Wenn tieferes Interesse an der Thematik bestehen sollte, habe ich hier noch ein paar Buchempfehlungen:
Rene Steiner: Grundkurs Relationale Datenbanken, Vieweg Verlag, ISBN: 978-3-8348-0710-6
Marcus Throll, Oliver Bartosch: Einstieg in SQL, Galileo Verlag, ISBN: 978-3-8362-1442-1