W MySQL, UNION
klauzula łączy wyniki z wielu zapytań w jeden zestaw wyników.
Przykład
Załóżmy, że mamy następujące tabele:
SELECT * FROM Teachers;
SELECT * FROM Students;
Wynik:
+-----------+-------------+ | 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 | +-----------+-------------+
Możemy wstawić UNION
klauzula między tymi dwoma SELECT
oświadczenia o zwrocie wszystkich nauczycieli i uczniów:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Wynik:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Nazwy kolumn są pobierane z pierwszego SELECT
oświadczenie.
Domyślnie UNION
klauzula niejawnie stosuje DISTINCT
operacja. Innymi słowy, domyślnie zwraca tylko różne wartości. Tak więc powyższe wyniki zawierają tylko po jednym z Warrena, Cathy i Billa. Dzieje się tak pomimo faktu, że połączone tabele faktycznie zawierają dwa Warrens, dwie Cathys i trzech Billów (jest dwóch nauczycieli o imieniu Cathy, nauczyciel i klient o imieniu Warren i dwóch o imieniu Bill, a także jeden uczeń o imieniu Bill).
Oto przykład, który jawnie używa DISTINCT
klauzula:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Wynik:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Więc otrzymujemy ten sam wynik, który otrzymaliśmy bez DISTINCT
klauzula.
Dołącz duplikaty
Możemy użyć ALL
słowo kluczowe, aby uwzględnić zduplikowane wartości w wynikach:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Wynik:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Tym razem otrzymaliśmy dwanaście wierszy zamiast ośmiu, które otrzymaliśmy w naszym pierwszym przykładzie.
Widzimy, że obie Cathys zostały zwrócone i wszystkie trzy rachunki zostały zwrócone.
TABLE
Oświadczenia
Od MySQL 8.0.19 możemy użyć UNION
klauzula z TABLE
oświadczenie.
Oto przykład:
TABLE Teachers
UNION
TABLE Students;
Wynik:
+-----------+-------------+ | 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 odpowiednik następującego zapytania:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Wynik:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Zauważysz, że te instrukcje zwracają więcej wierszy niż w naszym pierwszym przykładzie wcześniej. Dzieje się tak, ponieważ wybieramy wszystkie kolumny w tabeli, co skutkuje niepowielaniem tam, gdzie wcześniej był duplikat. Na przykład, dwóch nauczycieli o imieniu Bill zostało tu zwróconych, podczas gdy we wcześniejszym przykładzie powrócił tylko jeden. To dlatego, że TeacherId
kolumny zawierają różne wartości, dlatego wiersze nie są duplikatami.
Korzystanie z ORDER BY
Klauzula w kwerendach złożonych
Możemy użyć ORDER BY
klauzula w każdym SELECT
oświadczenie i/lub na połączonym UNION
zapytanie.
W każdym SELECT
Oświadczenie
Kiedy używamy ORDER BY
klauzula w indywidualnym SELECT
oświadczenia w ramach UNION
zapytanie, musimy dołączyć każde SELECT
oświadczenie w nawiasach:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Wynik:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 4 | Ein | +-----------+-------------+
Zauważ, że kiedy to robimy, w rzeczywistości nie porządkuje wyników dla wyjścia. Porządkuje wyniki tylko w celu określenia podzbioru wybranych wierszy do pobrania po zastosowaniu LIMIT
klauzula.
Dlatego używając ORDER BY
bez LIMIT
klauzula nie ma wpływu na wynik.
W całości UNION
Zapytanie
Możemy również użyć ORDER BY
klauzula na całe zapytanie, tak aby całe wyjście było uporządkowane razem.
W tym przykładzie weźmiemy poprzedni przykład i uporządkujemy połączone wyniki:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Wynik:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 4 | Ein | | 5 | Bill | | 6 | Bill | | 2 | Ben | +-----------+-------------+
Nawet jeśli nie używasz ORDER BY
klauzula w każdym SELECT
instrukcja, każdy SELECT
instrukcja powinna nadal znajdować się w nawiasach, a ORDER BY
klauzula (lub dowolny LIMIT
klauzula) powinna znajdować się po ostatniej.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Wynik:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Pamiętaj, że pominięcie nawiasów daje taki sam wynik jak ten z nawiasami:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Wynik:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Zwróć uwagę, że jeśli kolumna do sortowania używa aliasu, to do tej kolumny musi się odwoływać jego alias (nie nazwa kolumny).
Przykład:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Wynik:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Oto, co się stanie, jeśli nie użyjemy aliasu:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Wynik:
ERROR 1054 (42S22): Unknown column 'TeacherName' in 'order clause'
Liczba kolumn
Liczba kolumn zwracanych przez każdy SELECT
oświadczenie musi być takie samo. Dlatego nie możemy wykonać następujących czynności:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Wynik:
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Typy danych
Wybrane kolumny wymienione w odpowiednich pozycjach każdego SELECT
oświadczenie powinno mieć ten sam typ danych. Jeśli jednak nie, typy i długości kolumn w UNION
wynik uwzględnia wartości pobrane przez wszystkie SELECT
oświadczenia.
Oto, co się stanie, jeśli spróbujemy połączyć TeacherName
kolumna z StudentId
kolumna:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Wynik:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Niektóre inne RDBMS mogą wygenerować błąd w tym przypadku, ale MySQL udaje się wygenerować dane wyjściowe bez błędów.