Множественные операции в SQL
Теория: Объединение запросов
В этом уроке мы разберем оператор UNION. Чтобы попрактиковаться, мы возьмем нашу базу данных. В ней есть две таблицы с информацией о студентах, которые записывались на курсы в 2022 и 2023 году:
- course_members_2022
- course_members_2023
Обе таблицы имеют одинаковую структуру:
- Имя пользователя
- Название курса
- Дата записи на курс
Попробуем выяснить, кто записывался на курс по PHP в каждом году. Для этого выполним два запроса:
Выполнив эти запросы, мы получим две таблицы:
- С четырьмя пользователями за 2022 год
- С одним пользователем за 2023 год
php_course_memebers_22
php_course_memebers_23
Оператор UNION
Теперь объединим результаты этих запросов. Воспользуемся оператором UNION, который объединяет два запроса в один:
В результате мы получим пять строк:
php_course_memebers

Теперь попробуем объединить несколько запросов. Для этого укажем оператор UNION после каждого запроса:
course_memebers_2022
Обратите внимание, что объединять можно далеко не все запросы. Следите, чтобы выполнялись два правила:
- Во всех таблицах должно быть одинаковое количество столбцов
- Во всех таблицах должны быть одинаковые типы данных
Одинаковое количество столбцов
Если мы хотим объединить два подзапроса, они должны работать с одинаковым количеством столбцов. Посмотрите на запрос ниже:
Этот запрос выполнить не получится, потому что есть разница в столбцах:
- В первом подзапросе мы выводим два столбца — имя пользователя и дату записи
- Во втором подзапросе мы выводим только один столбец — имя пользователя
Чтобы исправить эту проблему, подправим второй подзапрос. Нам нужно либо вывести поле created_at в качестве второго столбца, либо заполнить этот столбец значением NULL.
Этот запрос выведет поле created_at для обоих подзапросов:
php_course_memebers
А этот — выведет во втором столбце значение NULL:
php_course_memebers
Одинаковые типы данных
Чтобы могли объединять запросы, важно и второе правило — чтобы оба запроса работали с одинаковыми типами данных. Попробуем объединить два подзапроса:
- В первом запросе укажем столбы
usernameиcreated_at(текст и дата) - Во втором запросе укажем столбцы
created_atиusername(дата и текст, то есть в обратном порядке)
Столбцы в подзапросах работают с разными типами данных, поэтому такой запрос не выполнится:
С этим правилом нужно быть аккуратнее. Дело в том, что СУБД проверяет только совпадение типов данных, но не их смысл. Посмотрим, к чему это может привести. В первом подзапросе укажем столбцы coursename и username, а во втором подзапросе - наоборот:
Запрос выполнится успешно, но в результирующей таблице мы увидим вперемешку ники студентов и названия курса. Это не то, что мы хотели получить.
course_memebers
Нет какого-то автоматического способа предотвратить эту ошибку, поэтому вам нужно следить за смыслом запроса самостоятельно.
Оператор UNION ALL
Перейдем к оператору UNION ALL и создадим два запроса о пользователях в 2022 году. В первом запросе изучим студентов курсов по Javascript, а во втором — курсов по Python:
Первый запрос выведет трех пользователей, а второй — двух. В целом мы получили пять записей.
js_course_memebers
python_course_memebers
А теперь объединим эти запросы с помощью UNION:
Этот запрос выведет нам только три записи.
course_memebers
Почему так произошло? Дело в том, что при объединении подзапросов UNION по умолчанию убирает дублирующиеся строки. Чтобы этого не происходило, добавим ALL к оператору UNION:
Такой запрос вывел нам пять строк, среди которых есть два одинаковых пользователя — Michaela11 и Duncan3.
course_memebers
course_memebers
Обратим внимание, что оператор
ORDER BY должен идти только в последнем подзапросе, если мы укажем его в первом, то такой запрос не сработает:
Выводы
В этом уроке вы научились объединять запросы с помощью оператора UNION. Чтобы запросы срабатывали, важно соблюдать два правила: объединяемые запросы должны иметь одинаковое количество столбцов, а сами столбцы — иметь одинаковые типы данных. По умолчанию UNION удаляет дублирующиеся строки. Если повторы нужно оставить, можно использовать оператор UNION ALL.
Обратим внимание, что запрос вывел результаты в произвольном порядке, никак не упорядоченными.
Чтобы упорядочить результаты, нам нужно воспользоваться оператором ORDER BY в последнем подзапросе. Если нужно упорядочить строки, то оператор ORDER BY нужно указывать в конец последнего подзапроса.
Рекомендуемые программы
Завершено
0 / 5

