Базовый курс SQL. Комбинированные запросы. Соединения. UNION
Primary tabs
Forums:
В обычном SQL-запросе мы используем ключевое слово SELECT
один раз, извлекая данные из одной или нескольких таблиц. Но возможности SQL позволяют также скомбинировать несколько таких запросов в один с помощью оператора UNION
, чтобы вернуть результат в едином наборе данных. Эти запросы называют комбинированными запросами, или соединениями.
Когда используются комбинированные запросы:
- когда нужно получить данные, структурированные одинаковым способом, но из разных таблиц
- когда нужно сделать несколько запросов к одной и той же таблице и получить данные в едином наборе
Многократные условия WHERE
В основном получается так, что результат комбинированного запроса к одной таблице аналогичен запросу к ней с множественными условиями WHERE
. Поэтому любой запрос с несколькими условиями WHERE
можно также считать комбинированным запросом.
Создание соединений
Синтаксис соединений очень простой: достаточно составить все запросы SELECT
, которые вам требуются и добавить между ними UNION
.
Рассмотрим соединение на примере. Предположим нам необходимо получить список иностранных студентов и добавить к нему тех, кто обучается в группе '117F'. Можно составить сложный запрос с условиями WHERE
, но в данном случае удобнее использовать соединение.
Для начала рассмотрим отдельно части запроса:
SELECT student_surname FROM Students WHERE student_country != 'РФ';
Получим:
student_surname ------------------------ Сейдинай Адамченко Легран
SELECT student_surname FROM Students WHERE group_id = (SELECT group_id FROM Groups WHERE group_name = '177F');
Получим второй список:
student_surname ------------------------ Легран Егорова Грошев
Теперь сделаем то же, но с помощью соединения UNION
:
SELECT student_surname FROM Students WHERE student_country != 'РФ' UNION SELECT student_surname FROM Students WHERE group_id = (SELECT group_id FROM Groups WHERE group_name = '117F');
Получим необходимый нам результат в одном наборе данных:
student_surname ------------------------ Сейдинай Легран Егорова Грошев Адамченко
И для сравнения рассмотрим тот же запрос с множественным условием WHERE
:
SELECT student_surname FROM Students WHERE student_country != 'РФ' OR group_id = (SELECT group_id FROM Groups WHERE group_name = '117F');
Запрос с помощью соединения может показаться громоздким по сравнению с множественным WHERE
, но зато он наглядно демонстрирует смысл того, что необходимо получить. С точки зрения поддержки кода часто это оправданный шаг, особенно если условия более сложные.
Сколько запросов можно соединять?
В стандарте SQL нет ограничений на число запросов SELECT
, соединяемых с помощью UNION
. Однако всегда лучше уточнять такие нюансы в документации конкретной СУБД.
Производительность соединений
В большинстве СУБД есть встроенный оптимизатор запросов, который комбинирует все SELECT
в соединении. Это означает, что разницы между несколькими условиями в одном запросе и несколькими целыми запросами нет. Но это только теоретически. На практике всегда лучше тестировать оба варианта, чтобы опытным путём убедиться в том, что выбран оптимальный метод.
Правила применения UNION
Определим некоторые правила, которые следует соблюдать, используя UNION
:
- Оператор
UNION
должен разделять все запросыSELECT
, сколько бы их не было - Соединения можно использовать только для получения одних и тех же полей таблиц. Т.е. имена столбцов и применяемые итоговые функции должны быть одинаковыми во всех запросах. В некоторых СУБД значение имеет даже их порядок.
- Типы данных запрашиваемых столбцов должны быть по крайней мере совместимы. Т.е. тип данных должен быть либо тот же, либо такой, который СУБД сможет преобразовать автоматически (например, различные форматы числа или даты)
Включить повторяющиеся строки
Рассмотрим внимательнее результаты отдельных запросов из предыдущего примера. Первый запрос возвращает 3 строки, второй - тоже 3. Но при их соединении, мы получаем 5 строк, а не 6. Так происходит потому, что UNION
по умолчанию исключает из выборки одинаковые результаты (так же сработал бы и запрос с несколькими условиями WHERE
). В нашем случае повторяющаяся строка - фамилия студента 'Легран'.
Если нам по каким-то причинам нужно получить все строки таблиц без исключения, применим оператор UNION ALL
:
SELECT student_surname FROM Students WHERE student_country != 'РФ' UNION ALL SELECT student_surname FROM Students WHERE group_id = (SELECT group_id FROM Groups WHERE group_name = '117F');
В результате 6 строк:
student_surname ----------------------- Сейдинай Адамченко Легран Егорова Легран Грошев
UNION ALL
или WHERE
В отличие от предыдущих примеров, WHERE
никак не сможет заменить UNION ALL
. Так что, если вы хотите получить полный список строк, вместе с дубликатами, используйте соединения.
Сортировка в соединениях
Т.к. результаты всех запросов соединения имеют одинаковую структуру, их с лёгкостью можно отсортировать. Оператор ORDER BY
при этом должен быть один для всех запросов и находиться после последнего оператора SELECT
.
Если вы примените сортировку несколько раз, СУБД выдаст ошибку.
Давайте дополним наше соединение:
SELECT student_surname FROM Students WHERE student_country != 'РФ' UNION SELECT student_surname FROM Students WHERE group_id = (SELECT group_id FROM Groups WHERE group_name = '117F') ORDER BY student_surname;
Фамилии будут отсортированы по алфавиту:
student_surname ----------------------- Адамченко Грошев Егорова Легран Сейдинай
Несмотря на то, что фактически ORDER BY
принадлежит только последнему запросу SELECT
, СУБД применит его ко всей полученной выборке.
Какие ещё бывают комбинированные запросы?
В некоторых СУБД есть и другие типы комбинированных соединений. Они создаются с помощью операторов EXCEPT
, или MINUS
, (позволяет извлечь строки, которые есть в первой таблице, но отсутствуют во второй) и INTERSECT
(позволяет извлечь только строки, имеющиеся в обоих таблицах). Но на практике для этих целей чаще используют объединения.
Соединения разных таблиц
На этом уроке мы рассмотрели соединения запросов к одной и той же таблице, но это не предел. Также UNION
можно использовать для разных таблиц - необходимо только следить за совместимостью типов данных. В таких случаях, если имена столбцов различаются, для их соединения придётся использовать псевдонимы.
Итак, сегодня мы узнали, как можно упростить сложные запросы с множественными условиями WHERE
. И как с помощью оператора UNION
получить результаты запросов из одной или нескольких таблиц в одной выборке.
- Log in to post comments
- 3690 reads