V MySQL je to UNION
klauzule kombinuje výsledky z více dotazů do jediné sady výsledků.
Příklad
Předpokládejme, že máme následující tabulky:
SELECT * FROM Teachers;
SELECT * FROM Students;
Výsledek:
+-----------+-------------+ | 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 | +-----------+-------------+
Můžeme vložit UNION
klauzule mezi těmito dvěma SELECT
příkazy k vrácení všech učitelů a studentů:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Výsledek:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Názvy sloupců jsou převzaty z prvního SELECT
prohlášení.
Ve výchozím nastavení UNION
klauzule implicitně aplikuje DISTINCT
úkon. Jinými slovy, ve výchozím nastavení vrací pouze odlišné hodnoty. Výše uvedené výsledky tedy obsahují pouze jeden Warren, Cathy a Bill. A to i přesto, že kombinované stoly ve skutečnosti obsahují dva Warreny, dvě Cathy a tři Billy (jsou tam dva učitelé Cathy, učitel a zákazník jménem Warren a dva Bill a jeden student Bill).
Zde je příklad, který explicitně používá DISTINCT
klauzule:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Výsledek:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Dostaneme tedy stejný výsledek, jaký jsme dostali bez DISTINCT
doložka.
Zahrnout duplikáty
Můžeme použít ALL
klíčové slovo pro zahrnutí duplicitních hodnot do výsledků:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Výsledek:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Tentokrát jsme dostali dvanáct řádků místo osmi, které jsme dostali v našem prvním příkladu.
Vidíme, že obě Cathy byly vráceny a všechny tři účty byly vráceny.
TABLE
Prohlášení
Od MySQL 8.0.19 můžeme použít UNION
klauzule s TABLE
prohlášení.
Zde je příklad:
TABLE Teachers
UNION
TABLE Students;
Výsledek:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
To je ekvivalent následujícího dotazu:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Výsledek:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Všimnete si, že tyto příkazy vrátí více řádků než v našem prvním příkladu dříve. Je to proto, že vybíráme všechny sloupce v tabulce, což vede k tomu, že tam, kde dříve duplikát byl, nejsou duplikáty. Zde jsou například vráceni dva učitelé jménem Bill, zatímco v předchozím příkladu byl vrácen pouze jeden. Je to proto, že TeacherId
sloupce obsahují různé hodnoty, takže řádky nejsou duplicitní.
Použití ORDER BY
Klauzule v Union Queries
Můžeme použít ORDER BY
klauzule v každém SELECT
příkazu a/nebo na kombinovaném UNION
dotaz.
V každém SELECT
Prohlášení
Když použijeme ORDER BY
klauzule v jednotlivém SELECT
příkazy v rámci UNION
dotaz, musíme uzavřít každý SELECT
prohlášení v závorkách:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Výsledek:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 4 | Ein | +-----------+-------------+
Všimněte si, že když to uděláme, ve skutečnosti to neseřadí výsledky pro výstup. Řadí výsledky pouze za účelem určení podmnožiny vybraných řádků, které se mají načíst při použití LIMIT
doložka.
Proto pomocí ORDER BY
bez LIMIT
klauzule nemá žádný vliv na výstup.
Celkově UNION
Dotaz
Můžeme také použít ORDER BY
klauzule na celý dotaz, takže celý výstup je uspořádán společně.
V tomto příkladu vezmeme předchozí příklad a seřadíme kombinované výsledky:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Výsledek:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 4 | Ein | | 5 | Bill | | 6 | Bill | | 2 | Ben | +-----------+-------------+
I když nepoužíváte ORDER BY
klauzule v každém SELECT
každý příkaz SELECT
příkaz by měl být stále v závorkách a ORDER BY
klauzule (nebo jakýkoli LIMIT
klauzule) by měla následovat za poslední.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Výsledek:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Pamatujte, že vynechání závorek vede ke stejnému výsledku jako v případě závorek:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Výsledek:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Všimněte si, že pokud sloupec, který má být seřazen, používá alias, pak na tento sloupec musí odkazovat jeho alias (nikoli název sloupce).
Příklad:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Výsledek:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Pokud alias nepoužijeme, stane se toto:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Výsledek:
ERROR 1054 (42S22): Unknown column 'TeacherName' in 'order clause'
Počet sloupců
Počet sloupců vrácených každým SELECT
prohlášení musí být stejné. Proto nemůžeme udělat následující:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Výsledek:
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Typy dat
Vybrané sloupce jsou uvedeny na odpovídajících pozicích každého SELECT
příkaz by měl mít stejný datový typ. Pokud však ne, typy a délky sloupců v UNION
výsledek bere v úvahu hodnoty načtené všemi SELECT
prohlášení.
Zde je to, co se stane, když se pokusíme zkombinovat TeacherName
sloupec s StudentId
sloupec:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Výsledek:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Některé jiné RDBMS by v tomto případě vytvořily chybu, ale MySQL zvládá produkovat výstup bez chyby.