Как объединить таблицы в sql
Перейти к содержимому

Как объединить таблицы в sql

  • автор:

Команда UNION

Команда UNION объединяет данные из нескольких таблиц в одну при выборке. При объединении количество столбцов во всех таблицах должно совпадать, иначе будет ошибка Имена столбцов будут такие же, как в основной таблице, в которую добавляются данные из других таблиц.

Внимание: если не используется ключевое слово ALL для UNION, все возвращенные строки будут уникальными, так как по умолчанию подразумевается DISTINCT , который удаляет неуникальные значения. Чтобы отменить такое поведение — нужно указать ключевое слово ALL , вот так: UNION ALL.

Синтаксис

С удалением дублей:

SELECT * FROM имя_таблицы1 WHERE условие UNION SELECT * FROM имя_таблицы2 WHERE условие

Без удаления дублей:

SELECT * FROM имя_таблицы1 WHERE условие UNION ALL SELECT * FROM имя_таблицы2 WHERE условие

Можно объединять не две таблицы, а три или более:

SELECT * FROM имя_таблицы1 WHERE условие UNION SELECT * FROM имя_таблицы2 WHERE условие UNION SELECT * FROM имя_таблицы3 WHERE условие UNION SELECT * FROM имя_таблицы4 WHERE условие

Таблицы для примеров

таблица countries

id
айди
name
название
1 Беларусь
2 Россия
3 Украина
таблица cities

id
айди
name
название
country_id
айди страны
1 Минск 1
2 Минск 1
3 Москва 2
4 Киев 3

Пример

В данном примере объединяются записи из двух таблиц:

SELECT id, name FROM countries UNION ALL SELECT id, name FROM cities

Результат выполнения кода:

id
айди
name
название
1 Беларусь
2 Россия
3 Украина
1 Минск
2 Минск
3 Москва
4 Киев

Пример

В данном примере отсутствует ключевое слово ALL, однако дубли не будут удалены, так как дублями считается полное совпадение строк:

SELECT id, name FROM countries UNION SELECT id, name FROM cities

Результат выполнения кода:

id
айди
name
название
1 Беларусь
2 Россия
3 Украина
1 Минск
2 Минск
3 Москва
4 Киев

Пример

А вот теперь дубли будут удалены (из двух Минсков останется один), так как будет иметь место полное совпадение строк (потому что поле осталось одно, но это не обязательно):

SELECT name FROM countries UNION SELECT name FROM cities

Результат выполнения кода:

name
название
Беларусь
Россия
Украина
Минск
Москва
Киев

Пример

А теперь добавим слово ALL — и дубли не будут удалятся:

SELECT name FROM countries UNION ALL SELECT name FROM cities

Результат выполнения кода:

name
название
Беларусь
Россия
Украина
Минск
Минск
Москва
Киев

Пример

В данном примере демонстрируется работа условий WHERE в комбинации с UNION:

SELECT id, name FROM countries WHERE id>=2 UNION SELECT id, name FROM cities WHERE id<=2

Результат выполнения кода:

id
айди
name
имя
2 Россия
3 Украина
1 Минск
2 Минск

Пример

Имена колонок берутся из первой таблицы (то есть имена колонок таблиц, подключенных через UNION нигде себя не проявят):

SELECT id as country_id, name as country_name FROM countries UNION SELECT id, name FROM cities

Результат выполнения кода:

country_id
айди
country_name
имя
1 Беларусь
2 Россия
3 Украина
1 Минск 1
2 Минск 1
3 Москва 2
4 Киев 3

Пример

Такой запрос выдаст ошибку, так как в таблицах не совпадает количество колонок:

SELECT id, name FROM countries UNION SELECT id, name, country_id FROM cities

И такой запрос тоже выдаст ошибку в нашем случае — количество колонок в обеих таблицах не совпадает:

SELECT * FROM countries UNION SELECT * FROM cities

Пример

Если нам очень надо забрать из какой-либо таблицы столько полей, что в другой таблице столько и нет, можно создавать дополнительные поля вручную.

К примеру, мы хотим забрать 3 поля из второй таблицы, а в первой таблице полей только 2 . Решим эту проблему создав поле с именем country_id и содержимым 0 для первой таблицы (вот так: 0 as country_id):

SELECT id, name, 0 as country_id FROM countries UNION SELECT id, name, country_id FROM cities

Результат выполнения кода:

id
айди
name
имя
country_id
айди страны
1 Беларусь 0
2 Россия 0
3 Украина 0
1 Минск 1
2 Минск 1
3 Москва 2
4 Киев 3

Смотрите также

  • команду JOIN ,
    которая объединяет связанные таблицы

Объединение таблиц – UNION

Операция UNION позволяет объединить несколько результатов выборки в один набор строк. Именно объединение строк отличает эту операцию от соединения таблиц через JOIN, которая присоединяет столбцы.

Рассмотрим пример.
Сначала придумаем две таблицы: с участниками забега; с работниками забега.

Имя_участника Место
Светлана 2
Алексей 4
Александр 1
Екатерина 5
Илья 3
Имя_работника Функция
Петр Менеджер
Иван Промоутер
Екатерина Врач
Кирилл Человек с водичкой

Теперь получим из таблиц уникальные имена всех людей.

--Сформируем первый набор из таблицы участников select Имя_участника as Имя from Участники union --Сформируем второй набор из таблицы работников select Имя_работника from Работники
Имя
Александр
Алексей
Екатерина
Иван
Илья
Кирилл
Петр
Светлана

Важно знать про UNION

Самый первый SELECT задает названия столбцам итоговой выборки.

Обратите внимание на то, что в вышеприведенном примере для уникальности имен не потребовалось использовать ключевое слово DISTINCT, т.к. операция UNION уникализирует строки после их объединения.
Если нужно получить все записи, в том числе одинаковые, то нужно использовать операцию UNION ALL вместо просто UNION.

Можно объединять более 2 наборов строк – просто продолжать писать «UNION SELECT …».

Количество столбцов должны совпадать во всех объединяемых наборах.
Типы данных для объединяемых столбцов должны совпадать или хотя бы иметь возможность неявно преобразовываться друг к другу. Например:

  • для набора №1 первый столбец имеет строковый тип VARCHAR, второй столбец числовой тип FLOAT;
  • для набора №2 первый столбец – VARCHAR, второй столбец – числовой тип INT.

Несмотря на то, что второй столбец для разных наборов отличается по типу данных, запрос все равно выполнится, т.к. INT будет преобразован к FLOAT.

Если требуется сделать сортировку полученной выборки, то предложение ORDER BY записывается в самом последнем селекте.

select col1, col2, col3 from Table1 union all select col1, col2, col3 from Table2 union all select col1, col2, col3 from Table3 order by col1 -- Сортируем весь результат
  • Объединение таблиц – UNION
  • Соединение таблиц – операция JOIN и ее виды
  • Тест на знание основ SQL

Если материалы office-menu.ru Вам помогли, то поддержите, пожалуйста, проект, чтобы я мог развивать его дальше.

Объединение таблиц при запросе (JOIN) в SQL

С помощью команды SELECT можно выбрать данные не только из одной таблицы, но и нескольких. Такая задача появляется довольно часто, потому что принято разносить данные по разным таблицам в зависимости от хранимой в них информации. К примеру, в одной таблице хранится информация о пользователях, во второй таблице о должностях компании, а в третьей и четвёртой о поставщиках и клиентах. Данные разбивают на таблицы так, чтобы с одной стороны получить самую высокую скорость выполнения запроса, а с другой стороны избежать ненужных объединений, которые снижают производительность.

Чем больше столбцов в таблице — тем сильнее падает скорость выборки из неё. Поэтому стараются делать в каждой таблице не больше 5-10 столбцов. Но чем сильнее данные разбиваются на разные таблицы, тем больше придётся делать объединений внутри запросов, что тоже снизит скорость получения выборки и увеличит нагрузку на базу.

Приведём пример запроса с объединением данных из двух таблиц. Для этого предположим, что существует две таблицы. Первая таблица будет иметь название USERS и будет иметь два столбца: ID и именами пользователей:

+-----------+ | USERS | +-----------+ | ID | NAME | +----+------+ | 1 | Мышь | +----+------+ | 2 | Кот | +----+------+

Вторая таблица будет называться FOOD и будет содержать два столбца: USER_ID и NAME. В этой таблице будет содержаться список любимых блюд пользователей из первой таблицы. В столбце USER_ID содержится ID пользователя, а в столбце PRODUCT находится название любимого блюда.

+-------------------+ | FOOD | +-------------------+ | USER_ID | PRODUCT | +---------+---------+ | 1 | Сыр | +---------+---------+ | 2 | Молоко | +---------+---------+

Условимся что поле ID в таблице USERS и поле USER_ID в таблице FOOD являются первичными ключами (то есть имеют уникальные значения, которые не повторяются). Теперь попробуем использовать логику и найти любимое блюдо пользователя «Мышь», используя обе таблицы. Для этого мы сначала посмотрим в первую таблицу и найдём ID пользователя под именем «Мышь», а затем найдём название продукта под таким же ID во второй таблице. Объединяющие SQL запросы работают по такой же логике: нужен столбец, в по которому таблицы могут быть объединены.

Продемонстрируем запрос, объединяющий таблицы по столбцам ID и USER_ID:

SELECT * FROM `USERS` INNER JOIN `FOOD` ON `USERS`.`ID`=`FOOD`.`USER_ID`;

Разберём команду по словам. Начинается она как обычная выборка из одной таблицы со слов «SELECT * FROM USERS». Но затем идёт слово INNER, которое означает тип объединения. Существует три типа объединения таблиц: INNER, LEFT, RIGHT. Все они связаны с тем, что некоторым строкам в одной таблице может не найтись соответствующей строки во второй таблице. В таком случае при использовании «INNER» из результатов запроса будет удалены все строки, которым не нашлась соответствующая пара в другой таблице. Если же использовать вместо «INNER» слово «LEFT» или «RIGHT», то будут удалены строки, которые не нашли совпадение из первой (левой) или второй (правой) таблицы.

После слова «INNER» стоит слово «JOIN» (которое переводится с английского как «ПРИСОЕДИНИТЬ»). После слова «JOIN» стоит название таблицы, которая будет присоединена. В нашем случае это таблица FOOD. После названия таблицы стоит слово «ON» и равенство USERS.ID=FOOD.USER_ID, которое задаёт правило присоединения. При выполнении выборки будут объединены две таблицы так, чтобы значения в столбце ID таблицы USERS равнялось значению USER_ID таблицы FOOD.

В результате выполнения этого SQL запроса мы получим таблицу с четырьмя столбцами:

+----+------+---------+---------+ | ID | NAME | USER_ID | PRODUCT | +----+------+---------+---------+ | 1 | Мышь | 1 | Сыр | +----+------+---------+---------+ | 2 | Кот | 2 | Молоко | +----+------+---------+---------+

Предлагаем модифицировать запрос, потому что нам не нужны все четыре столбца. Уберём столбцы ID и USER_ID. Для этого вместо * в команде SELECT поставим название столбцов. Но необходимо сделать это, ставя сначала название таблицы и через точку название столбца. Чтобы получилось так:

SELECT `USERS`.`NAME`, `FOOD`.`PRODUCT` FROM `USERS` INNER JOIN `FOOD` ON `USERS`.`ID`=`FOOD`.`USER_ID`;

Теперь результат будет компактнее. И благодаря уменьшенному количеству запрашиваемых данных, результат будет получаться из базы быстрее:

+------+---------+ | NAME | PRODUCT | +------+---------+ | Мышь | Сыр | +------+---------+ | Кот | Молоко | +------+---------+

Если в двух таблицах имеются столбцы с одинаковыми названиями, то будет показан только последний столбце с таким названием. Чтобы этого не происходило, выбирайте определённый столбцы и используйте команду «AS» с помощью которой можно переименовать столбец в результатах выборки.

Давайте теперь решим логическую задачу, которую поставили в начале статьи. Попробуем выбрать в этой объединённой таблице только одну строку, которая соответствует пользователю «Мышь». Для этого используем условие WHERE в SQL запросе:

SELECT `USERS`.`NAME`, `FOOD`.`PRODUCT` FROM `USERS` INNER JOIN `FOOD` ON `USERS`.`ID`=`FOOD`.`USER_ID` WHERE `USERS`.`NAME` LIKE 'Мышь';

Обратите внимание, что в условии WHERE название полей так же необходимо ставить вместе с названием таблицы через точку: USERS.NAME. В результате выполнения этого запроса появится такой результат:

+------+---------+ | NAME | PRODUCT | +------+---------+ | Мышь | Сыр | +------+---------+

Типы соединения

Доработаем наш недавний запрос про поиск более низкой цены на товар в другом магазине. Будем искать товар в другом магазине, с ценой хотя бы на 1500 дешевле:

SELECT pp.product_id, pp.store_id, pp.price, ppl.store_id AS store_id_less, ppl.price AS price_less FROM product_price pp JOIN product_price ppl ON ppl.product_id = pp.product_id AND ppl.store_id != pp.store_id AND ppl.price < pp.price - 1500 ORDER BY pp.product_id, pp.store_id, ppl.store_id, ppl.price 

Запрос вернет всего 2 записи

product_id store_id price store_id_less price_less
1 301 12500.00 300 10500.00
4 500 22000.00 400 20000.00

Что делать, если хочется оставить в выборке товары, для которых не нашлось аналогичного более дешевого товара в другом магазине? На помощь приходят так называемые внешние соединения. Существуют следующие типы соединений:

  • INNER JOIN или просто JOIN - внутреннее соединение. В результате остаются только те строки, для которых нашлось соответствие. До сих пор мы использовали только этот тип соединений.
  • LEFT JOIN - левое внешнее соединение. Работает как JOIN , но если для строки таблицы, находящейся по левую сторону ключевого слова LEFT JOIN , не нашлось ни одной строки в таблице, находящейся по правую сторону LEFT JOIN , то строка все равно добавляется в результат, а значения столбцов правой таблицы равны null .
  • RIGHT JOIN - правое внешнее соединение. Работает как JOIN , но если для строки таблицы, находящейся по правую сторону ключевого слова RIGHT JOIN , не нашлось ни одной строки в таблице, находящейся по левую сторону RIGHT JOIN , то строка все равно добавляется в результат, а значения столбцов левой таблицы равны null .
  • FULL JOIN - полное внешнее соединение. Если для какой-либо из таблиц не нашлось строки в другой таблице, то строка все равно попадает в результат, а значения столбцов другой таблицы равны null .
  • CROSS JOIN - перекрестное (или декартово) произведение. Каждая строка одной таблицы соединяется с каждой строкой второй таблицы, давая тем самым в результате все возможные сочетания строк двух таблиц. Аналогичного результата можно достичь просто перечислив таблицы в FROM через запятую.

Перепишем запрос с использованием LEFT JOIN :

SELECT pp.product_id, pp.store_id, pp.price, ppl.store_id AS store_id_less, ppl.price AS price_less FROM product_price pp LEFT JOIN product_price ppl ON ppl.product_id = pp.product_id AND ppl.store_id != pp.store_id AND ppl.price < pp.price - 1500 ORDER BY pp.product_id, pp.store_id, ppl.store_id, ppl.price 
product_id store_id price store_id_less price_less
1 300 10500.00
1 301 12500.00 300 10500.00
1 800 12000.00
2 500 26100.00
. . . . .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *