I MySQL, UNION
sats kombinerar resultaten från flera frågor till en enda resultatuppsättning.
Exempel
Anta att vi har följande 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 infoga UNION
klausul mellan dessa två SELECT
uttalanden för att returnera alla lärare och elever:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Kolumnnamnen är hämtade från den första SELECT
uttalande.
Som standard är UNION
satsen tillämpar implicit en DISTINCT
drift. Med andra ord returnerar den endast distinkta värden som standard. Så ovanstående resultat innehåller bara ett vardera av Warren, Cathy och Bill. Detta trots att de kombinerade tabellerna faktiskt innehåller två Warrens, två Cathys och tre Bills (det finns två lärare som heter Cathy, en lärare och en kund som heter Warren, och två som heter Bill, samt en elev som heter Bill).
Här är ett exempel som uttryckligen använder 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 samma resultat som vi fick utan DISTINCT
klausul.
Inkludera dubbletter
Vi kan använda ALL
sökord för att inkludera dubbletter av värden i resultaten:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Den här gången fick vi tolv rader istället för de åtta som vi fick i vårt första exempel.
Vi kan se att båda Cathys returnerades och alla tre räkningarna returnerades.
TABLE
Uttalanden
Från MySQL 8.0.19 kan vi använda UNION
sats med TABLE
påstående.
Här är ett exempel:
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 motsvarar följande fråga:
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 kommer att märka att dessa påståenden returnerar fler rader än i vårt första exempel tidigare. Det beror på att vi väljer alla kolumner i tabellen, vilket resulterar i icke-dubbletter där det tidigare fanns en dubblett. Till exempel returneras två lärare som heter Bill här medan endast en returnerades i det tidigare exemplet. Det beror på att TeacherId
kolumner innehåller olika värden, därför är raderna inte dubbletter.
Använda ORDER BY
Klausul i Union Queries
Vi kan använda ORDER BY
sats i varje SELECT
uttalande och/eller på den kombinerade UNION
fråga.
I varje SELECT
Uttalande
När vi använder ORDER BY
sats i den individuella SELECT
uttalanden inom en UNION
fråga måste vi bifoga varje SELECT
uttalande inom 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 | +-----------+-------------+
Observera att när vi gör detta ordnar det faktiskt inte resultaten för utdata. Den ordnar bara resultaten i syfte att bestämma delmängden av de valda raderna som ska hämtas när LIMIT
tillämpas klausul.
Använd därför ORDER BY
utan LIMIT
klausulen har ingen effekt på utdata.
I det hela UNION
Fråga
Vi kan också använda en ORDER BY
sats på hela frågan, så att hela utdata ordnas tillsammans.
I det här exemplet tar vi det föregående exemplet och beställer de kombinerade resultaten:
(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 | +-----------+-------------+
Även när du inte använder ORDER BY
sats inom varje SELECT
sats, varje SELECT
satsen ska fortfarande stå inom parentes och ORDER BY
klausul (eller någon LIMIT
sats) bör vara efter den sista.
(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 | +-----------+-------------+
Tänk på, att utelämna parentesen ger samma resultat som den 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 | +-----------+-------------+
Observera att om en kolumn som ska sorteras använder ett alias, måste den kolumnen refereras av dess alias (inte kolumnnamnet).
Exempel:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Resultat:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Så här händer om vi inte använder 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 kolumner
Antalet kolumner som returneras av varje SELECT
uttalandet måste vara detsamma. Därför kan vi inte göra följande:
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
Valda kolumner listade i motsvarande positioner för varje SELECT
uttalandet ska ha samma datatyp. Men om de inte gör det, typ och längd på kolumnerna i UNION
resultatet tar hänsyn till de värden som hämtas av alla SELECT
uttalanden.
Här är vad som händer om vi försöker kombinera TeacherName
kolumnen med StudentId
kolumn:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Resultat:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Vissa andra RDBMS skulle ge ett fel i det här fallet, men MySQL lyckas producera utdata utan fel.