UNION und UNION ALL in SQL: Ergebnisse clever kombinieren

Was ist UNION in SQL? – Eine einfache Erklärung

Stell dir vor, du hast zwei Listen – eine mit Kunden aus Berlin und eine mit Kunden aus München. Beide Listen haben dieselbe Struktur: Name, E-Mail, Stadt. Jetzt möchtest du eine einzige Gesamtliste aller Kunden erstellen. Genau hier kommt UNION ins Spiel.

UNION ist ein SQL-Operator, der die Ergebnisse von zwei oder mehr SELECT-Abfragen zu einem einzigen Ergebnis zusammenfasst. Du stapelst also quasi mehrere Abfrageergebnisse übereinander – Zeile für Zeile.

Wann braucht man UNION überhaupt?

Es gibt typische Situationen, in denen UNION unverzichtbar wird:

  • Du hast Daten, die auf mehrere Tabellen verteilt sind, aber dieselbe Struktur haben – zum Beispiel Bestellungen aus verschiedenen Jahren in getrennten Tabellen.
  • Du möchtest Ergebnisse aus verschiedenen Abfragen auf derselben Tabelle kombinieren, etwa aktive und archivierte Einträge.
  • Du pflegst historische Daten in separaten Tabellen und willst eine Gesamtauswertung erstellen.

Visualisierung: Zwei Tabellen werden zu einer

Das Prinzip ist denkbar einfach. Du hast zwei Tabellen mit gleichem Aufbau:

Tabelle: kunden_berlin

name email
Anna Müller anna@example.com
Ben Schmidt ben@example.com

Tabelle: kunden_muenchen

name email
Clara Weber clara@example.com
Ben Schmidt ben@example.com

Mit UNION kombiniert, entsteht daraus eine einzige Ergebnismenge. Was dabei mit dem doppelten Eintrag von Ben Schmidt passiert – und warum das von deiner Wahl zwischen UNION und UNION ALL abhängt – erklärt sich im nächsten Abschnitt.

Union Union All

Syntax von UNION und UNION ALL

Bevor wir uns die Unterschiede zwischen UNION und UNION ALL anschauen, werfen wir einen Blick auf den grundlegenden Aufbau. Die Syntax ist erfreulich übersichtlich.

Grundaufbau mit Code-Beispiel

So sieht eine typische UNION-Abfrage aus:

SELECT name, email FROM kunden_berlin
UNION
SELECT name, email FROM kunden_muenchen;

Und das Pendant mit UNION ALL:

SELECT name, email FROM kunden_berlin
UNION ALL
SELECT name, email FROM kunden_muenchen;

Du schreibst also einfach zwei vollständige SELECT-Abfragen und verbindest sie mit UNION oder UNION ALL dazwischen. So einfach ist der Einstieg.

Regeln: Gleiche Spaltenanzahl, kompatible Datentypen

Damit UNION funktioniert, müssen zwei Bedingungen zwingend erfüllt sein:

  • Gleiche Spaltenanzahl: Jede SELECT-Abfrage muss exakt dieselbe Anzahl an Spalten zurückliefern. Wenn die erste Abfrage drei Spalten selektiert, muss die zweite das ebenfalls tun.
  • Kompatible Datentypen: Die Spalten an jeder Position müssen zueinander kompatible Datentypen haben. Du kannst keine Textspalte mit einer Zahlenspalte kombinieren.

Die Spaltennamen im Ergebnis richten sich übrigens immer nach der ersten SELECT-Abfrage. Was die zweite Abfrage als Spaltenname hat, wird ignoriert – nur die Werte zählen.

Ein Beispiel, das verdeutlicht, wie du auch unterschiedlich benannte Spalten kombinieren kannst:

SELECT vorname AS name, email FROM kunden_berlin
UNION
SELECT vollstaendiger_name, kontakt_email FROM kunden_muenchen;

Im Ergebnis erscheint die Spalte als name – weil die erste Abfrage diesen Alias vorgibt. Die zweite Abfrage liefert lediglich die Werte.

UNION vs. UNION ALL – Was ist der Unterschied?

Das ist die Frage, die sich fast jeder stellt, der UNION zum ersten Mal begegnet. Der Unterschied ist schnell erklärt – aber er hat spürbare Auswirkungen auf dein Ergebnis und die Performance deiner Abfrage.

UNION entfernt Duplikate

UNION kombiniert die Ergebnisse beider Abfragen und entfernt dabei automatisch alle doppelten Zeilen. Zwei Zeilen gelten als Duplikat, wenn sie in allen Spalten identische Werte haben.

Nehmen wir unser Beispiel von vorhin. Ben Schmidt taucht in beiden Tabellen auf:

SELECT name, email FROM kunden_berlin
UNION
SELECT name, email FROM kunden_muenchen;

Ergebnis:

name email
Anna Müller anna@example.com
Ben Schmidt ben@example.com
Clara Weber clara@example.com

Ben Schmidt erscheint nur einmal, obwohl er in beiden Tabellen vorhanden war. UNION hat das Duplikat still und leise entfernt.

UNION ALL behält alle Zeilen

UNION ALL macht dasselbe – kombiniert beide Ergebnismengen – verzichtet aber vollständig auf die Duplikatprüfung. Jede Zeile landet im Ergebnis, egal ob sie bereits vorhanden ist oder nicht.

SELECT name, email FROM kunden_berlin
UNION ALL
SELECT name, email FROM kunden_muenchen;

Ergebnis:

name email
Anna Müller anna@example.com
Ben Schmidt ben@example.com
Clara Weber clara@example.com
Ben Schmidt ben@example.com

Ben Schmidt taucht jetzt zweimal auf. Das ist kein Fehler – es ist genau das erwartete Verhalten von UNION ALL.

Vergleichstabelle: UNION vs. UNION ALL

Eigenschaft UNION UNION ALL
Duplikate im Ergebnis Nein, werden entfernt Ja, bleiben erhalten
Performance Langsamer (Duplikatprüfung) Schneller (keine Prüfung)
Anwendungsfall Wenn Eindeutigkeit wichtig ist Wenn alle Zeilen gebraucht werden
Sortierung des Ergebnisses Nicht garantiert Nicht garantiert

Die Faustregel lautet: Weißt du bereits, dass keine Duplikate entstehen können, oder brauchst du bewusst alle Zeilen – nimm UNION ALL. Brauchst du eine bereinigte, eindeutige Liste – nimm UNION.

Praxisbeispiele: UNION und UNION ALL im Einsatz

Theorie ist gut – aber an konkreten Beispielen wird klarer, wann du welchen Operator sinnvoll einsetzt. Hier sind drei typische Szenarien aus dem Alltag.

Beispiel 1: Kundenlisten aus zwei Filialen zusammenführen

Du betreibst zwei Filialen und pflegst die Kundendaten getrennt in zwei Tabellen: kunden_berlin und kunden_muenchen. Für einen Newsletter möchtest du eine bereinigte Gesamtliste aller Kunden – ohne doppelte Einträge.

SELECT name, email FROM kunden_berlin
UNION
SELECT name, email FROM kunden_muenchen;

Hier ist UNION die richtige Wahl. Kunden, die in beiden Filialen registriert sind, sollen im Newsletter nur einmal angeschrieben werden. Die automatische Duplikatbereinigung erledigt das für dich.

Beispiel 2: Verkaufsdaten über mehrere Jahre aggregieren

Deine Verkaufsdaten sind nach Jahren in separate Tabellen aufgeteilt: verkäufe_2023 und verkäufe_2024. Du möchtest eine Gesamtauswertung über beide Jahre erstellen und dabei jeden einzelnen Verkauf berücksichtigen – auch wenn derselbe Artikel mehrfach verkauft wurde.

SELECT artikel, menge, umsatz FROM verkaeufe_2023
UNION ALL
SELECT artikel, menge, umsatz FROM verkaeufe_2024;

Hier ist UNION ALL klar die bessere Wahl. Jeder Verkaufsvorgang ist ein eigenständiger Datensatz. Würdest du UNION verwenden, riskierst du, dass identische Buchungen – zum Beispiel zweimal derselbe Artikel für denselben Betrag – aus deiner Auswertung verschwinden. Das würde deine Zahlen verfälschen.

Beispiel 3: Aktive und archivierte Einträge kombinieren

Du hast eine Tabelle projekte_aktiv und eine Tabelle projekte_archiv. Für einen Gesamtbericht möchtest du alle Projekte auflisten – unabhängig davon, ob sie noch laufen oder bereits abgeschlossen sind.

SELECT projektname, status, startdatum FROM projekte_aktiv
UNION ALL
SELECT projektname, status, startdatum FROM projekte_archiv
ORDER BY startdatum DESC;

Auch hier macht UNION ALL Sinn, weil es grundsätzlich keine echten Duplikate geben sollte – ein Projekt existiert entweder in der aktiven oder in der archivierten Tabelle, nicht in beiden. Die zusätzliche Duplikatprüfung von UNION wäre in diesem Fall unnötiger Overhead.

Beachte außerdem das ORDER BY am Ende: Es sortiert das gesamte kombinierte Ergebnis – nicht nur eine der beiden Abfragen. Mehr dazu im Abschnitt über die Kombination mit anderen SQL-Klauseln.

Performance: Wann ist UNION ALL die bessere Wahl?

Wer SQL nicht nur korrekt, sondern auch effizient schreiben möchte, kommt an der Performance-Frage nicht vorbei. Und hier hat UNION ALL einen klaren Vorteil gegenüber UNION.

Warum UNION langsamer sein kann

Wenn du UNION verwendest, muss die Datenbank nach dem Zusammenführen der Ergebnisse einen zusätzlichen Arbeitsschritt durchführen: Sie vergleicht jede Zeile mit allen anderen, um Duplikate zu identifizieren und zu entfernen. Technisch gesehen entspricht das intern häufig einer DISTINCT-Operation über das gesamte Ergebnis.

Das klingt harmlos – wird aber zum Problem, sobald du mit größeren Datenmengen arbeitest. Denn der Aufwand für diesen Vergleich wächst mit der Anzahl der Zeilen. Die Datenbank muss unter Umständen temporäre Strukturen anlegen, Daten sortieren oder hashen, um Duplikate effizient zu finden. All das kostet Zeit und Ressourcen.

UNION ALL überspringt diesen Schritt vollständig. Die Ergebnisse beider Abfragen werden einfach aneinandergehängt – fertig. Kein Vergleich, kein Sortieren, kein Bereinigen. Das macht UNION ALL in der Regel spürbar schneller, besonders bei:

  • großen Tabellen mit vielen Zeilen
  • Abfragen, die mehrere UNION-Verknüpfungen hintereinander verwenden
  • zeitkritischen Berichten oder Dashboards, die regelmäßig ausgeführt werden

Faustregel für die Praxis

Die Entscheidung zwischen UNION und UNION ALL lässt sich auf eine einfache Frage herunterbrechen:

Können in deinem Ergebnis überhaupt Duplikate entstehen – und stören sie dich?

  • Nein, Duplikate sind strukturell ausgeschlossen – zum Beispiel weil die Tabellen voneinander unabhängige Datensätze enthalten: Nimm UNION ALL.
  • Ja, Duplikate können entstehen, aber du brauchst sie nicht: Nimm UNION.
  • Ja, Duplikate können entstehen, und du brauchst sie bewusst – zum Beispiel für eine vollständige Protokollauswertung: Nimm UNION ALL.

Im Zweifel ist UNION ALL die performantere Wahl. Wenn du sicherstellen willst, dass keine Duplikate im Ergebnis landen, aber trotzdem auf Performance achten möchtest, kannst du alternativ ein DISTINCT nachgelagert einsetzen – oder die Duplikatbereinigung bewusst nur auf die Spalten beschränken, die wirklich relevant sind.

Häufige Fehler und wie du sie vermeidest

Auch wenn UNION und UNION ALL auf den ersten Blick simpel wirken, gibt es einige Stolperfallen, die besonders Einsteigern regelmäßig begegnen. Hier sind die häufigsten Fehler – und wie du sie von Anfang an vermeidest.

Spaltenanzahl stimmt nicht überein

Das ist der klassische Fehler Nummer eins. Wenn die beiden SELECT-Abfragen eine unterschiedliche Anzahl an Spalten zurückliefern, quittiert die Datenbank das mit einer Fehlermeldung.

-- Falsch: erste Abfrage hat 3 Spalten, zweite nur 2
SELECT name, email, stadt FROM kunden_berlin
UNION
SELECT name, email FROM kunden_muenchen;

Die Lösung ist einfach: Beide Abfragen müssen dieselbe Spaltenanzahl haben. Wenn eine Tabelle eine bestimmte Information nicht enthält, kannst du einen Platzhalterwert verwenden:

-- Richtig: zweite Abfrage gibt NULL als Platzhalterwert für stadt zurück
SELECT name, email, stadt FROM kunden_berlin
UNION
SELECT name, email, NULL AS stadt FROM kunden_muenchen;

Inkompatible Datentypen

Die Spalten an jeder Position müssen zueinander kompatible Datentypen haben. Eine Textspalte lässt sich nicht ohne Weiteres mit einer Zahlenspalte kombinieren.

-- Falsch: erste Spalte ist Text, zweite ist eine Zahl
SELECT name FROM kunden
UNION
SELECT kundennummer FROM bestellungen;

In vielen Datenbanksystemen führt das zu einem Fehler – oder schlimmer: zu einer stillen impliziten Konvertierung, die deine Ergebnisse verfälscht. Die saubere Lösung ist eine explizite Typumwandlung mit CAST:

-- Richtig: Zahl wird explizit in Text umgewandelt
SELECT name FROM kunden
UNION
SELECT CAST(kundennummer AS VARCHAR) FROM bestellungen;

ORDER BY falsch platziert

Ein häufiges Missverständnis ist, ORDER BY innerhalb einer der Teilabfragen zu verwenden. Das ist in den meisten Datenbanksystemen nicht erlaubt und führt zu einem Fehler.

-- Falsch: ORDER BY innerhalb einer Teilabfrage
SELECT name, email FROM kunden_berlin ORDER BY name
UNION
SELECT name, email FROM kunden_muenchen;

ORDER BY gehört immer ans Ende der gesamten UNION-Abfrage und sortiert das komplette kombinierte Ergebnis:

-- Richtig: ORDER BY am Ende der gesamten Abfrage
SELECT name, email FROM kunden_berlin
UNION
SELECT name, email FROM kunden_muenchen
ORDER BY name;

UNION mit unterschiedlichen Spaltennamen verwechseln

Ein subtiler, aber wichtiger Punkt: Die Spaltennamen im Ergebnis orientieren sich immer an der ersten SELECT-Abfrage. Wenn du in der zweiten Abfrage andere Spaltennamen oder Aliase verwendest, haben diese keinerlei Auswirkung auf das Ergebnis.

SELECT vorname AS name FROM kunden_berlin
UNION
SELECT vollstaendiger_name AS kompletter_name FROM kunden_muenchen;

Im Ergebnis heißt die Spalte name – nicht kompletter_name. Wer das nicht weiß, wundert sich später beim Weiterverarbeiten der Ergebnisse, warum der selbst gewählte Alias der zweiten Abfrage schlicht ignoriert wird.

UNION mit ORDER BY, WHERE und GROUP BY kombinieren

In der Praxis reicht ein einfaches UNION oder UNION ALL oft nicht aus. Du möchtest das Ergebnis sortieren, filtern oder aggregieren. Hier zeigen wir dir, wie das sauber funktioniert – und worauf du achten musst.

Sortieren des Gesamtergebnisses mit ORDER BY

Wie im vorherigen Abschnitt bereits angesprochen: ORDER BY gehört immer ans Ende der gesamten Abfrage. Es wirkt dann auf das vollständige kombinierte Ergebnis.

SELECT name, email, stadt FROM kunden_berlin
UNION ALL
SELECT name, email, stadt FROM kunden_muenchen
ORDER BY name ASC;

Du kannst sowohl den Spaltennamen als auch die Spaltenposition zur Sortierung verwenden. Letzteres ist praktisch, wenn du lange Abfragen schreibst:

SELECT name, email, stadt FROM kunden_berlin
UNION ALL
SELECT name, email, stadt FROM kunden_muenchen
ORDER BY 1 ASC;

Die 1 steht hier für die erste Spalte im Ergebnis – also name. Bedenke aber, dass diese Schreibweise die Lesbarkeit deiner Abfrage verschlechtert. Im Team-Umfeld ist der explizite Spaltenname die bessere Wahl.

Filtern vor und nach dem UNION

Du hast zwei Möglichkeiten, einen Filter mit WHERE einzusetzen: innerhalb der einzelnen Teilabfragen oder um das gesamte Ergebnis herum.

Filter innerhalb der Teilabfragen – sinnvoll, wenn du je Tabelle unterschiedliche Bedingungen brauchst:

SELECT name, email, stadt FROM kunden_berlin WHERE registriert_seit > '2023-01-01'
UNION ALL
SELECT name, email, stadt FROM kunden_muenchen WHERE registriert_seit > '2022-01-01';

Filter auf das gesamte Ergebnis – hier musst du die UNION-Abfrage als Unterabfrage verpacken:

SELECT * FROM (
    SELECT name, email, stadt FROM kunden_berlin
    UNION ALL
    SELECT name, email, stadt FROM kunden_muenchen
) AS alle_kunden
WHERE stadt = 'Berlin';

Der Alias alle_kunden nach der schließenden Klammer ist dabei in den meisten Datenbanksystemen Pflicht – ohne ihn gibt es einen Fehler.

Aggregieren mit GROUP BY

Auch GROUP BY lässt sich auf das kombinierte Ergebnis anwenden, indem du wieder eine Unterabfrage verwendest. Ein typischer Anwendungsfall: Du möchtest wissen, wie viele Kunden du insgesamt pro Stadt hast – über alle Filialen hinweg.

SELECT stadt, COUNT(*) AS anzahl_kunden
FROM (
    SELECT name, email, stadt FROM kunden_berlin
    UNION ALL
    SELECT name, email, stadt FROM kunden_muenchen
) AS alle_kunden
GROUP BY stadt
ORDER BY anzahl_kunden DESC;

Dieses Muster – UNION ALL als Unterabfrage, darüber eine Aggregation – ist in der Praxis sehr verbreitet. Es ist sauber, gut lesbar und performant, weil UNION ALL keine unnötige Duplikatprüfung durchführt, bevor die Aggregation die Daten ohnehin zusammenfasst.

Fazit: UNION oder UNION ALL – welches wann?

Du hast jetzt einen vollständigen Überblick über UNION und UNION ALL – von der Grundsyntax über Praxisbeispiele bis hin zu Performance und häufigen Fehlern. Zeit für eine abschließende Orientierungshilfe.

Die Wahl zwischen den beiden Operatoren ist letztlich keine Glaubensfrage, sondern eine sachliche Entscheidung auf Basis zweier Kriterien: Was soll dein Ergebnis enthalten – und wie schnell soll die Abfrage sein?

Kurze Entscheidungshilfe als Checkliste

Nimm UNION, wenn:

  • du eine bereinigte, eindeutige Ergebnismenge benötigst
  • Duplikate inhaltlich falsch wären – zum Beispiel bei einer Newsletter-Liste, in der jede Person nur einmal erscheinen soll
  • du nicht sicher bist, ob die kombinierten Datenquellen überschneidungsfreie Datensätze enthalten

Nimm UNION ALL, wenn:

  • du weißt oder sichergestellt hast, dass keine Duplikate entstehen können
  • du bewusst alle Zeilen brauchst – auch doppelte – etwa bei Transaktions- oder Protokolldaten
  • Performance eine Rolle spielt und die Duplikatprüfung unnötiger Overhead wäre
  • du das kombinierte Ergebnis anschließend ohnehin mit GROUP BY aggregierst

Als allgemeine Empfehlung gilt: Starte mit UNION ALL als Standard und wechsle bewusst zu UNION, wenn du die Duplikatbereinigung tatsächlich benötigst. So bleibst du auf der performanteren Seite – ohne auf Korrektheit zu verzichten.

Mit diesem Wissen bist du gut gerüstet, um beide Operatoren gezielt und sicher in deinen SQL-Abfragen einzusetzen. Viel Erfolg beim Ausprobieren.