I MySQL er UNION
klausul kombinerer resultaterne fra flere forespørgsler til et enkelt resultatsæt.
Eksempel
Antag, at vi har følgende tabeller:
SELECT * FROM Teachers;
SELECT * FROM Students;
Resultat:
+-----------+-------------+ | 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 | +-----------+-------------+
Vi kan indsætte UNION
klausul mellem disse to SELECT
erklæringer for at returnere alle lærere og elever:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Kolonnenavnene er taget fra den første SELECT
erklæring.
Som standard er UNION
klausul anvender implicit en DISTINCT
operation. Med andre ord returnerer det kun distinkte værdier som standard. Så ovenstående resultater indeholder kun én af hver af Warren, Cathy og Bill. Dette er på trods af, at de kombinerede tabeller faktisk indeholder to Warrens, to Cathys og tre Bills (der er to lærere, der hedder Cathy, en lærer og en kunde, der hedder Warren, og to, der hedder Bill, samt en elev, der hedder Bill).
Her er et eksempel, der eksplicit bruger DISTINCT
klausul:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Så vi får det samme resultat, som vi fik uden DISTINCT
klausul.
Medtag dubletter
Vi kan bruge ALL
søgeord for at inkludere duplikerede værdier i resultaterne:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Denne gang fik vi tolv rækker i stedet for de otte, som vi fik i vores første eksempel.
Vi kan se, at begge Cathys blev returneret, og alle tre regninger blev returneret.
TABLE
Udtalelser
Fra MySQL 8.0.19 kan vi bruge UNION
klausul med TABLE
udmelding.
Her er et eksempel:
TABLE Teachers
UNION
TABLE Students;
Resultat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Det svarer til følgende forespørgsel:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Resultat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Du vil bemærke, at disse udsagn returnerer flere rækker end i vores første eksempel tidligere. Det skyldes, at vi udvælger alle kolonner i tabellen, hvilket resulterer i ikke-duplikater, hvor der tidligere var en dublet. For eksempel returneres to lærere kaldet Bill her, mens kun én blev returneret i det tidligere eksempel. Det er fordi TeacherId
kolonner indeholder forskellige værdier, derfor er rækkerne ikke dubletter.
Brug af ORDER BY
Klausul i Union Queries
Vi kan bruge ORDER BY
klausul i hver SELECT
sætning og/eller på den kombinerede UNION
forespørgsel.
I hver SELECT
Erklæring
Når vi bruger ORDER BY
klausul i den individuelle SELECT
udsagn i en UNION
forespørgsel, skal vi vedlægge hver SELECT
sætning inden for parentes:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Resultat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 4 | Ein | +-----------+-------------+
Bemærk, at når vi gør dette, bestiller det faktisk ikke resultaterne for outputtet. Den bestiller kun resultaterne med det formål at bestemme delmængden af de valgte rækker, der skal hentes ved anvendelse af LIMIT
klausul.
Brug derfor ORDER BY
uden LIMIT
klausul har ingen effekt på outputtet.
I det hele taget UNION
Forespørgsel
Vi kan også bruge en ORDER BY
klausul på hele forespørgslen, så hele outputtet er ordnet sammen.
I dette eksempel tager vi det foregående eksempel og bestiller de kombinerede resultater:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Resultat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 4 | Ein | | 5 | Bill | | 6 | Bill | | 2 | Ben | +-----------+-------------+
Selv når du ikke bruger ORDER BY
klausul inden for hver SELECT
sætning, hver SELECT
sætningen skal stadig stå i parentes, og ORDER BY
klausul (eller en hvilken som helst LIMIT
klausul) skal være efter den sidste.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Resultat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Husk, at udeladelse af parentes giver det samme resultat som det med parentes:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Resultat:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Bemærk, at hvis en kolonne, der skal sorteres, bruger et alias, skal den kolonne refereres til ved sit alias (ikke kolonnenavnet).
Eksempel:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Resultat:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Her er hvad der sker, hvis vi ikke bruger aliaset:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Resultat:
ERROR 1054 (42S22): Unknown column 'TeacherName' in 'order clause'
Antal kolonner
Antallet af kolonner, der returneres af hver SELECT
udsagnet skal være det samme. Derfor kan vi ikke gøre følgende:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Resultat:
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Datatyper
Valgte kolonner opført i tilsvarende positioner for hver SELECT
sætningen skal have samme datatype. Men hvis de ikke gør det, typerne og længderne af kolonnerne i UNION
resultat tage højde for værdierne hentet af alle SELECT
udsagn.
Her er, hvad der sker, hvis vi prøver at kombinere TeacherName
kolonne med StudentId
kolonne:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Nogle andre RDBMS'er ville producere en fejl i dette tilfælde, men MySQL formår at producere output uden fejl.