Zum Inhalt
wannacode

UNION, INTERSECT, EXCEPT und CROSS JOIN

Kurz gesagt: UNION vereint die Ergebnisse zweier Abfragen, INTERSECT behält die gemeinsamen Zeilen, EXCEPT entfernt die Zeilen der zweiten aus der ersten, und CROSS JOIN liefert jedes Paar von Zeilen.

Problem

Eine Liste aus zwei Quellen

Der Shop verschickt einen Herbst-Newsletter an seine aktiven Kunden. Aktiv ist jeder, der seit dem 1. September 2026 bestellt oder seit dem 1. Juni eine Bewertung geschrieben hat.

Bestellungen und Bewertungen stehen in verschiedenen Tabellen. Verbindest du sie mit JOIN, bleiben nur die Kunden übrig, die beides haben. Wir brauchen die beiden Listen, untereinander gelegt.

Die Idee

UNION

UNION legt das Ergebnis der zweiten Abfrage unter das der ersten und entfernt die Wiederholungen:

SQLDatenbank: Shop

11 Kunden. Jede der beiden Abfragen ist vollständig, mit eigenem FROM, JOIN und WHERE. Die Spaltennamen kommen von der ersten.

UNION ALL behält auch die Wiederholungen:

SQLDatenbank: Shop

17 Zeilen: Fünf Kunden kommen mehrfach vor (mit mehreren Bestellungen oder mit einer Bestellung und einer Bewertung). Der Newsletter braucht UNION, sonst bekommt jemand die E-Mail dreimal. UNION ALL ist dafür da, wenn jede Zeile ein eigenes Ereignis ist und gezählt werden muss.

Probier es aus

Eine Kaffeeverkostung

Der Shop lädt alle, die Kaffeebohnen (Produkt 17) gekauft oder eine Bewertung dazu geschrieben haben, zu einer Verkostung ein. Zeige ihre Namen, jeden einmal.

SQLDatenbank: Shop

Sieh es dir an

Die Spalten müssen übereinstimmen

Die beiden Abfragen liefern Zeilen für ein und dieselbe Tabelle, also müssen sie gleich viele Spalten haben:

SQLDatenbank: Shop

Spalten werden nach Position gepaart, nicht nach Namen. Wenn die erste Abfrage name, email liefert, muss auch die zweite zwei Spalten liefern, und in sinnvoller Reihenfolge: Name unter Name.

Für die ganze Geschichte eines Kunden füge eine Spalte hinzu, die sagt, woher die Zeile kommt. Marias Bestellungen und Bewertungen, nach Datum:

SQLDatenbank: Shop

ORDER BY am Ende sortiert das ganze Ergebnis, nicht nur die zweite Abfrage. Die Spalten heißen day und event, wie in der ersten Abfrage.

Die Idee

INTERSECT und EXCEPT

INTERSECT behält die Zeilen, die in beiden Ergebnissen stehen. Die Produkte, die bestellt wurden und auch eine Bewertung haben:

SQLDatenbank: Shop

13 Produkte. Das sind genau die Produkte mit einer Bewertung, denn jedes Produkt wurde bestellt (das hast du in der Lektion über LEFT JOIN gesehen).

EXCEPT behält die Zeilen des ersten Ergebnisses, die nicht im zweiten stehen. Die Produkte ohne Bewertung:

SQLDatenbank: Shop

12 Produkte. LEFT JOIN reviews … WHERE r.id IS NULL liefert dasselbe. EXCEPT liest sich wie ein Satz: „alle Produkte, abzüglich derer mit einer Bewertung“. Bei EXCEPT zählt die Reihenfolge der Abfragen, bei UNION und INTERSECT nicht.

Probier es aus

Um eine Bewertung bitten

Welche Produkte wurden seit dem 1. September 2026 gekauft, haben aber gar keine Bewertung? Ihre Käufer werden um eine gebeten. Zeige die Produktnamen.

SQLDatenbank: Shop

Die Idee

CROSS JOIN

Manchmal brauchst du jedes Paar. Der Bericht nach Stadt und Kategorie muss eine Zeile für jede Stadt und jede Unterkategorie haben, auch wo es keine Verkäufe gibt. Das Raster entsteht mit CROSS JOIN: jede Zeile der einen Tabelle mit jeder Zeile der anderen, ohne ON.

SQLDatenbank: Shop

6 Städte mal 6 Unterkategorien, 36 Zeilen. DISTINCT ist nötig, weil sich die Stadt in customers wiederholt: Ohne es sind es 114 Zeilen, eine für jeden Kunden mit Stadt und jede Unterkategorie.

Das Raster mit den Verkäufen (und den Nullen) zu füllen, lernst du im Modul über Unterabfragen. Das Raster ist die erste Hälfte.

Sieh es dir an

Achte auf die Anzahl der Zeilen

CROSS JOIN multipliziert. 60 Bestellungen und 152 Bestellpositionen:

SQLDatenbank: Shop

9.120 Paare, fast alle sinnlos. Dasselbe passiert, wenn du ON vergisst. In SQLite ist ein JOIN ohne ON ein CROSS JOIN, ohne Fehler:

SQLDatenbank: Shop

1.200 Zeilen (60 × 20) statt 60. PostgreSQL meldet in diesem Fall einen Fehler. Wenn ein Bericht plötzlich viel mehr Zeilen oder viel mehr Geld zeigt als erwartet, prüfe zuerst die Bedingungen in ON.

Übung

Das Raster der obersten Kategorien

Der Jahresbericht geht nach Stadt und oberster Kategorie („Lebensmittel“, „Haushalt“). Bau das Raster: jede Stadt (ohne die leere) mit jeder obersten Kategorie, jedes Paar einmal.

SQLDatenbank: Shop
Genauer, für Neugierige

UNION in SQLite liefert die Zeilen oft sortiert, weil es so die Wiederholungen entfernt. Das ist nicht versprochen. Wann immer die Reihenfolge zählt, schreib ORDER BY ans Ende.

INTERSECT und EXCEPT gibt es in SQLite, PostgreSQL und SQL Server. In Oracle heißt EXCEPT MINUS, und neuere Versionen verstehen auch EXCEPT. MySQL hat sie seit Version 8.0.31.

Test

Teste dich

1. Was ist der Unterschied zwischen UNION und UNION ALL?
2. Welche Produkte liefert A EXCEPT B, wenn A die bestellten sind und B die mit einer Bewertung?
3. Warum ergibt SELECT name, email … UNION SELECT name … einen Fehler?
4. Eine Tabelle mit 60 Zeilen CROSS JOIN eine Tabelle mit 152 Zeilen. Wie viele Zeilen kommen heraus?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·