Руководство по SQL. Объединения.

Для комбинирования результатов двух и более 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       |
| NULL | NULL              | Feature#3   | 2016-06-15 |
+------+-------------------+-------------+------------+


Элемент 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 |
| NULL | NULL              | Feature#3   | 2016-06-15 |
+------+-------------------+-------------+------------+

Как мы видим, таблица содержит результаты обоих запросов SELECT и данные повторяются.

Существует два других оператора, чьё поведение крайне схоже с UNION:

  • INTERSECT
    Комбинирует два запроса SELECT, но возвращает записи только первого SELECT, которые имеют совпадения во втором элементе SELECT.
  • EXCEPT
    Комбинирует два запроса SELECT, но возвращает записи только первого SELECT, которые не имеют совпадения во втором элементе SELECT.

На этом мы заканчиваем изучение способов объединения данных.
В следующей статье мы рассмотрим индексы.