In MySQL is de UNION
clausule combineert de resultaten van meerdere zoekopdrachten in een enkele resultaatset.
Voorbeeld
Stel dat we de volgende tabellen hebben:
SELECT * FROM Teachers;
SELECT * FROM Students;
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | +-----------+-------------+ +-----------+-------------+ | StudentId | StudentName | +-----------+-------------+ | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | | 6 | Bill | +-----------+-------------+
We kunnen de UNION
. invoegen clausule tussen die twee SELECT
verklaringen om alle docenten en studenten terug te geven:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Resultaat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
De kolomnamen zijn afkomstig uit de eerste SELECT
verklaring.
Standaard is de UNION
clausule past impliciet een DISTINCT
toe operatie. Met andere woorden, het retourneert standaard alleen afzonderlijke waarden. Dus de bovenstaande resultaten bevatten slechts één van Warren, Cathy en Bill. Dit ondanks het feit dat de gecombineerde tabellen eigenlijk twee Warrens, twee Cathys en drie Bills bevatten (er zijn twee docenten genaamd Cathy, een docent en een klant genaamd Warren, en twee genaamd Bill, evenals een student genaamd Bill).
Hier is een voorbeeld dat expliciet de DISTINCT
. gebruikt clausule:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Resultaat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
We krijgen dus hetzelfde resultaat als zonder de DISTINCT
clausule.
Duplicaten opnemen
We kunnen de ALL
. gebruiken zoekwoord om dubbele waarden in de resultaten op te nemen:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Resultaat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Deze keer kregen we twaalf rijen in plaats van de acht die we in ons eerste voorbeeld kregen.
We kunnen zien dat beide Cathy's zijn geretourneerd en alle drie de rekeningen zijn geretourneerd.
TABLE
Verklaringen
Vanaf MySQL 8.0.19 kunnen we de UNION
. gebruiken clausule met de TABLE
uitspraak.
Hier is een voorbeeld:
TABLE Teachers
UNION
TABLE Students;
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Dat is het equivalent van de volgende vraag:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
U zult merken dat deze instructies meer rijen retourneren dan in ons eerste voorbeeld eerder. Dat komt omdat we alle kolommen in de tabel selecteren, wat resulteert in niet-duplicaten waar er eerder een duplicaat was. Er worden hier bijvoorbeeld twee leraren met de naam Bill geretourneerd, terwijl er in het eerdere voorbeeld slechts één werd geretourneerd. Dat komt omdat de TeacherId
kolommen bevatten verschillende waarden, daarom zijn de rijen geen duplicaten.
De ORDER BY
gebruiken Clausule in Union Queries
We kunnen de ORDER BY
. gebruiken clausule in elke SELECT
statement en/of op de gecombineerde UNION
vraag.
In elke SELECT
Verklaring
Wanneer we de ORDER BY
. gebruiken clausule in de individuele SELECT
verklaringen binnen een UNION
query, moeten we elke SELECT
verklaring tussen haakjes:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 4 | Ein | +-----------+-------------+
Houd er rekening mee dat wanneer we dit doen, de resultaten voor de uitvoer niet echt worden geordend. Het bestelt de resultaten alleen om de subset van de geselecteerde rijen te bepalen die moet worden opgehaald bij het toepassen van de LIMIT
clausule.
Gebruik daarom ORDER BY
zonder de LIMIT
clausule heeft geen effect op de uitvoer.
Over het geheel genomen UNION
Zoekopdracht
We kunnen ook een ORDER BY
. gebruiken clausule op de hele query, zodat de hele uitvoer samen wordt besteld.
In dit voorbeeld nemen we het vorige voorbeeld en rangschikken we de gecombineerde resultaten:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 4 | Ein | | 5 | Bill | | 6 | Bill | | 2 | Ben | +-----------+-------------+
Zelfs als u de ORDER BY
. niet gebruikt clausule binnen elke SELECT
statement, elke SELECT
statement moet nog steeds tussen haakjes staan, en de ORDER BY
clausule (of een LIMIT
clausule) moet na de laatste staan.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Let op, het weglaten van de haakjes levert hetzelfde resultaat op als het resultaat met haakjes:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Resultaat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Houd er rekening mee dat als een te sorteren kolom een alias gebruikt, naar die kolom moet worden verwezen door zijn alias (niet de kolomnaam).
Voorbeeld:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Resultaat:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Dit is wat er gebeurt als we de alias niet gebruiken:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Resultaat:
ERROR 1054 (42S22): Unknown column 'TeacherName' in 'order clause'
Aantal kolommen
Het aantal kolommen dat wordt geretourneerd door elke SELECT
verklaring moet hetzelfde zijn. Daarom kunnen we het volgende niet doen:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Resultaat:
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Gegevenstypen
Geselecteerde kolommen weergegeven in corresponderende posities van elke SELECT
statement moet hetzelfde gegevenstype hebben. Als dit echter niet het geval is, worden de typen en lengtes van de kolommen in de UNION
resultaat houdt rekening met de waarden die zijn opgehaald door alle SELECT
verklaringen.
Dit is wat er gebeurt als we proberen de TeacherName
te combineren kolom met de StudentId
kolom:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Resultaat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Sommige andere RDBMS'en zouden in dit geval een fout produceren, maar MySQL slaagt erin om uitvoer zonder fouten te produceren.