В MySQL, UNION
клауза комбинира резултатите от множество заявки в един набор от резултати.
Пример
Да предположим, че имаме следните таблици:
SELECT * FROM Teachers;
SELECT * FROM Students;
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 1 | Уорън || 2 | Бен || 3 | Кати || 4 | Кати || 5 | Бил || 6 | Сметка |+-----------+-------------++-----------+-------- -----+| StudentId | Име на ученик |+-----------+------------+| 1 | Фей || 2 | Реактивен || 3 | Спайк || 4 | Ein || 5 | Уорън || 6 | Сметка |+-----------+------------+
Можем да вмъкнем UNION
клауза между тези две SELECT
изявления за връщане на всички учители и ученици:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Резултат:
+------------+| Име на учителя |+------------+| Уорън || Бен || Кати || Бил || Фей || Реактивен || Спайк || Ein |+------------+
Имената на колоните са взети от първия SELECT
изявление.
По подразбиране UNION
клаузата имплицитно прилага DISTINCT
операция. С други думи, той връща само различни стойности по подразбиране. Така че горните резултати съдържат само по един от Уорън, Кати и Бил. Това е въпреки факта, че комбинираните таблици всъщност съдържат двама Уорън, две Кати и три Била (има двама учители, наречени Кати, учител и клиент, наречен Уорън, и двама, наречени Бил, както и един ученик, наречен Бил).
Ето пример, който изрично използва DISTINCT
клауза:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Резултат:
+------------+| Име на учителя |+------------+| Уорън || Бен || Кати || Бил || Фей || Реактивен || Спайк || Ein |+------------+
Така получаваме същия резултат, който получихме без DISTINCT
клауза.
Включване на дубликати
Можем да използваме ALL
ключова дума, за да включите дублиращи се стойности в резултатите:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Резултат:
+------------+| Име на учителя |+------------+| Уорън || Бен || Кати || Кати || Бил || Бил || Фей || Реактивен || Спайк || Ein || Уорън || Сметка |+------------+
Този път получихме дванадесет реда вместо осемте, които получихме в първия ни пример.
Можем да видим, че и двете Кати бяха върнати и трите законопроекта бяха върнати.
TABLE
Изявления
От MySQL 8.0.19 можем да използваме UNION
клауза с TABLE
изявление.
Ето един пример:
TABLE Teachers
UNION
TABLE Students;
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 1 | Уорън || 2 | Бен || 3 | Кати || 4 | Кати || 5 | Бил || 6 | Бил || 1 | Фей || 2 | Реактивен || 3 | Спайк || 4 | Ein || 5 | Уорън |+-----------+------------+
Това е еквивалент на следната заявка:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 1 | Уорън || 2 | Бен || 3 | Кати || 4 | Кати || 5 | Бил || 6 | Бил || 1 | Фей || 2 | Реактивен || 3 | Спайк || 4 | Ein || 5 | Уорън |+-----------+------------+
Ще забележите, че тези изрази връщат повече редове, отколкото в първия ни пример по-рано. Това е така, защото избираме всички колони в таблицата, което води до недублиране, където преди е имало дубликат. Например двама учители, наречени Бил, са върнати тук, докато само един е върнат в предишния пример. Това е така, защото TeacherId
колоните съдържат различни стойности, следователно редовете не са дублирани.
Използване на ORDER BY
Клауза в заявките за съюз
Можем да използваме ORDER BY
клауза във всеки SELECT
изявление и/или на комбинирания UNION
запитване.
Във всеки SELECT
Изявление
Когато използваме ORDER BY
клауза в отделния SELECT
изрази в рамките на UNION
заявка, трябва да оградим всеки SELECT
изявление в скоби:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 2 | Бен || 5 | Бил || 6 | Бил || 4 | Ein |+-----------+------------+
Имайте предвид, че когато правим това, това всъщност не подрежда резултатите за изхода. Той подрежда резултатите само с цел определяне на подмножеството от избраните редове за извличане при прилагане на LIMIT
клауза.
Следователно, използвайте ORDER BY
без LIMIT
клаузата няма ефект върху изхода.
Като цяло UNION
Запитване
Можем също да използваме ORDER BY
клауза за цялата заявка, така че целият изход да бъде подреден заедно.
В този пример вземаме предишния пример и подреждаме комбинираните резултати:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 4 | Ein || 5 | Бил || 6 | Бил || 2 | Бен |+-----------+------------+
Дори когато не използвате ORDER BY
клауза във всеки SELECT
израз, всеки SELECT
операторът все още трябва да е в скоби, а ORDER BY
клауза (или който и да е LIMIT
клауза) трябва да е след последната.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 2 | Бен || 5 | Бил || 6 | Бил || 3 | Кати || 4 | Кати || 4 | Ein || 1 | Фей || 2 | Реактивен || 3 | Спайк || 1 | Уорън || 5 | Уорън |+-----------+------------+
Имайте предвид, че пропускането на скоби води до същия резултат като този със скоби:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Резултат:
+-----------+------------+| Идентификатор на учителя | Име на учителя |+-----------+------------+| 2 | Бен || 5 | Бил || 6 | Бил || 3 | Кати || 4 | Кати || 4 | Ein || 1 | Фей || 2 | Реактивен || 3 | Спайк || 1 | Уорън || 5 | Уорън |+-----------+------------+
Имайте предвид, че ако колона, която трябва да бъде сортирана, използва псевдоним, тогава тази колона трябва да бъде посочена от нейния псевдоним (а не името на колоната).
Пример:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Резултат:
<пред>+--------+| t |+--------+| Бен || Бил || Кати || Ein || Фей || Реактивен || Спайк || Уорън |+--------+Ето какво се случва, ако не използваме псевдонима:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Резултат:
ГРЕШКА 1054 (42S22):Неизвестна колона „Име на учител“ в „клауза за поръчка“
Брой колони
Броят на колоните, върнати от всеки SELECT
изявлението трябва да е същото. Следователно не можем да направим следното:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Резултат:
ГРЕШКА 1222 (21000):Използваните изрази SELECT имат различен брой колони
Типове данни
Избрани колони, изброени на съответните позиции на всеки SELECT
изявлението трябва да има същия тип данни. Ако обаче не го направят, типовете и дължините на колоните в UNION
резултатът взема предвид стойностите, извлечени от всички SELECT
изявления.
Ето какво се случва, ако се опитаме да комбинираме TeacherName
колона с StudentId
колона:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Резултат:
+------------+| Име на учителя |+------------+| Уорън || Бен || Кати || Бил || 1 || 2 || 3 || 4 || 5 || 6 |+------------+
Някои други RDBMS биха довели до грешка в този случай, но MySQL успява да произведе изход без грешка.