Для комбинирования результатов двух и более SQL запросов без возвращения повторяющихся данных используется оператор UNION.
Для того, чтобы мы могли использовать данный оператор, каждый из запросов SELECT должен содержать одинаковое количество выбранных колонок, одинаковое количество выражений, одинаковые типы данных и иметь одинаковый порядок.
Запрос с использованием оператора UNION имеет следующий вид:
SELECT колонка1 [, колонка2 ]
FROM таблица1 [, таблица2 ]
[WHERE условие]
UNION
SELECT колонка1 [, колонка2 ]
FROM таблица1 [, таблица2 ]
[WHERE условие]
Пример:
Предположим, что у нас есть две таблицы:
developers:
+----+-------------------+------------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+------------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 2500 |
| 2 | Peter Romanenko | Java | 3 | 3500 |
| 3 | Andrei Komarov | JavaScript | 3 | 2500 |
| 4 | Konstantin Geiko | C# | 2 | 2000 |
| 5 | Asya Suleimanova | UI/UX | 2 | 1800 |
| 6 | Kolya Nikolaev | Javascript | 5 | 3400 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
| 8 | Ludmila Geiko | UI/UX | 2 | 1800 |
+----+-------------------+------------+------------+--------+
tasks:
+---------+-------------+------------------+------------+--------------+
| TASK_ID | TASK_NAME | DESCRIPTION | DEADLINE | DEVELOPER_ID |
+---------+-------------+------------------+------------+--------------+
| 1 | Bug#123 | Fix company list | 2016-06-03 | 1 |
| 2 | Bug#321 | Fix registration | 2016-06-06 | 2 |
| 3 | Feature#777 | Latest actions | 2016-06-25 | 3 |
+---------+-------------+------------------+------------+--------------+
Попробуем выполнить следующий запрос:
mysql> SELECT ID, NAME, TASK_NAME, DEADLINE
FROM developers
LEFT JOIN tasks
ON developers.ID = tasks.DEVELOPER_ID
UNION
SELECT ID, NAME, TASK_NAME, DEADLINE
FROM developers
RIGHT JOIN tasks
ON developers.ID = tasks.DEVELOPER_ID;
В результате мы получим следующий результат:
+------+-------------------+-------------+------------+
| ID | NAME | TASK_NAME | DEADLINE |
+------+-------------------+-------------+------------+
| 1 | Eugene Suleimanov | Bug#123 | 2016-06-03 |
| 2 | Peter Romanenko | Bug#321 | 2016-06-06 |
| 3 | Andrei Komarov | Feature#777 | 2016-06-25 |
| 4 | Konstantin Geiko | NULL | NULL |
| 5 | Asya Suleimanova | NULL | NULL |
| 6 | Kolya Nikolaev | NULL | NULL |
| 7 | Ivan Ivanov | NULL | NULL |
| 8 | Ludmila Geiko | NULL | NULL |
+------+-------------------+-------------+------------+
Элемент UNION ALL
Элемент UNION ALL комбинирует результаты двух запросов SELECT, исключая повторяющиеся записи.
Данный запрос имеет следующий вид:
SELECT колонка1 [, колонка2 ]
FROM таблица1 [, таблица2 ]
[WHERE условие]
UNION ALL
SELECT колонка1 [, колонка2 ]
FROM таблица1 [, таблица2 ]
[WHERE условие]
Пример:
Предположим, что у нас есть две таблицы:
developers:
+----+-------------------+------------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+------------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 2500 |
| 2 | Peter Romanenko | Java | 3 | 3500 |
| 3 | Andrei Komarov | JavaScript | 3 | 2500 |
| 4 | Konstantin Geiko | C# | 2 | 2000 |
| 5 | Asya Suleimanova | UI/UX | 2 | 1800 |
| 6 | Kolya Nikolaev | Javascript | 5 | 3400 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
| 8 | Ludmila Geiko | UI/UX | 2 | 1800 |
+----+-------------------+------------+------------+--------+
tasks:
+---------+-------------+------------------+------------+--------------+
| TASK_ID | TASK_NAME | DESCRIPTION | DEADLINE | DEVELOPER_ID |
+---------+-------------+------------------+------------+--------------+
| 1 | Bug#123 | Fix company list | 2016-06-03 | 1 |
| 2 | Bug#321 | Fix registration | 2016-06-06 | 2 |
| 3 | Feature#777 | Latest actions | 2016-06-25 | 3 |
+---------+-------------+------------------+------------+--------------+
Попробуем выполнить следующий запрос:
mysql> SELECT ID, NAME, TASK_NAME, DEADLINE
FROM developers
LEFT JOIN tasks
ON developers.ID = tasks.DEVELOPER_ID
UNION ALL
SELECT ID, NAME, TASK_NAME, DEADLINE
FROM developers
RIGHT JOIN tasks
ON developers.ID = tasks.DEVELOPER_ID;
В результате мы получим следующую таблицу:
+------+-------------------+-------------+------------+
| ID | NAME | TASK_NAME | DEADLINE |
+------+-------------------+-------------+------------+
| 1 | Eugene Suleimanov | Bug#123 | 2016-06-03 |
| 2 | Peter Romanenko | Bug#321 | 2016-06-06 |
| 3 | Andrei Komarov | Feature#777 | 2016-06-25 |
| 4 | Konstantin Geiko | NULL | NULL |
| 5 | Asya Suleimanova | NULL | NULL |
| 6 | Kolya Nikolaev | NULL | NULL |
| 7 | Ivan Ivanov | NULL | NULL |
| 8 | Ludmila Geiko | NULL | NULL |
| 1 | Eugene Suleimanov | Bug#123 | 2016-06-03 |
| 2 | Peter Romanenko | Bug#321 | 2016-06-06 |
| 3 | Andrei Komarov | Feature#777 | 2016-06-25 |
+------+-------------------+-------------+------------+
Как мы видим, таблица содержит результаты обоих запросов SELECT и данные повторяются.
Существует два других оператора, чьё поведение крайне схоже с UNION:
- INTERSECT
Комбинирует два запроса SELECT, но возвращает записи только первого SELECT, которые имеют совпадения во втором элементе SELECT. - EXCEPT
Комбинирует два запроса SELECT, но возвращает записи только первого SELECT, которые не имеют совпадения во втором элементе SELECT.
На этом мы заканчиваем изучение способов объединения данных.
В следующей статье мы рассмотрим индексы.