для чего нужен оператор union

Команда UNION

Основные запросы

Условия выборки

Группировка

Сложение строк

Несколько таблиц

Длина строк

Изменение строк

Поиск по строкам

Работа с пробелами

Работа с регистром

Информация

Условия

Полезное

Разное

Математические функции

Списки

Извлечение части даты

Получение даты и времени

Преобразование даты

Сложение дат

Тригонометрия

Отдельные символы

Системы счисления

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

При объединении количество столбцов во всех таблицах должно совпадать, иначе будет ошибка

Имена столбцов будут такие же, как в основной таблице, в которую добавляются данные из других таблиц.

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

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

Синтаксис

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

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

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

Примеры

Все примеры будут по таблицам countries и cities, если не сказано иное.

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

Пример

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

SQL запрос выберет следующие строки:

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

Пример

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

SQL запрос выберет следующие строки:

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

Пример

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

SQL запрос выберет следующие строки:

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

Пример

SQL запрос выберет следующие строки:

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

Пример

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

SQL запрос выберет следующие строки:

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

Пример

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

SQL запрос выберет следующие строки:

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

Пример

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

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

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

Источник

Операторы работы с наборами — UNION (Transact-SQL)

Сцепляет результаты двух запросов в один результирующий набор. Вы указываете, будет ли результирующий набор включать повторяющиеся строки:

Операция UNION отличается от операции JOIN :

Ниже приведены основные правила объединения результирующих наборов двух запросов с помощью операции UNION:

количество и порядок столбцов должны быть одинаковыми во всех запросах;

типы данных должны быть совместимыми.

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор unionСинтаксические обозначения в Transact-SQL

Синтаксис

Ссылки на описание синтаксиса Transact-SQL для SQL Server 2014 и более ранних версий, см. в статье Документация по предыдущим версиям.

Аргументы

| ( ) Это спецификация запроса или выражение запроса, возвращающее данные для объединения с данными из другой спецификации запроса или выражения запроса. Определения столбцов, которые являются частью операции UNION, не должны совпадать, однако должны быть совместимыми посредством неявного преобразования. Если типы данных различаются, то получившийся тип данных определяется на основе правил очередности типов данных. Если типы одинаковы, но различаются по точности, масштабу или длине, результат определяется на основе тех же самых правил, которые действуют при объединении выражений. Дополнительные сведения см. в разделе Точность, масштаб и длина (Transact-SQL).

Столбцы типа данных xml должны быть эквивалентны друг другу. Все столбцы должны либо иметь тип, определенный в XML-схеме, либо быть нетипизированными. Типизированные столбцы должны относиться к одной и той же коллекции XML-схем.

UNION
Указывает на то, что несколько результирующих наборов следует объединить и возвратить в виде единого результирующего набора.

ALL
Объединяет в результирующий набор все строки, в том числе повторяющиеся. Если обратное не указано, дубликаты строк удаляются.

Примеры

A. Использование простого UNION

Б. Использование SELECT INTO с UNION

В. Использование UNION двух инструкций SELECT с ORDER BY

Г. Использование UNION трех инструкций SELECT для демонстрации эффекта от использования скобок и ALL

Примеры: Azure Synapse Analytics и Система платформы аналитики (PDW)

Д. Использование простого UNION

Е. Использование UNION двух инструкций SELECT с ORDER BY

Ж. Использование UNION двух инструкций SELECT с WHERE и ORDER BY

З. Использование UNION трех инструкций SELECT для демонстрации эффекта от использования скобок и ALL

Источник

SQL урок 4. операторы sql Union, Exists; строковые функции

SQL запрос Union (объединение)

Над множеством можно выполнять операции объединения, разности и декартова произведения. Те же операции можно использовать и в sql запросах (выполнять операции с запросами).

Для объединения нескольких запросов используется служебное слово UNION.
Синтаксис:

SQL запрос Union служит для объединения выходных строк каждого запроса в один результирующий набор.

Если используется параметр ALL, то сохраняются все дубликаты выходных строк. Если параметр отсутствует, то в результирующем наборе остаются только уникальные строки.

Объединять вместе можно любое число запросов.

Использование оператора UNION требует выполнения нескольких условий:

Рассмотрим более сложный пример с объединением inner join:

SQL Предикат существования EXISTS

Предикат EXISTS принимает значение TRUE (истина), если подзапрос возвращает хоть какое-нибудь количество строк, иначе EXISTS принимает значение FALSE. Существует также предикат NOT EXISTS, который действует противоположным образом.

Обычно EXISTS используется в зависимых подзапросах (например, IN).

SELECT DISTINCT Производитель FROM product AS pc_product WHERE Тип = «Компьютер» AND EXISTS ( SELECT Производитель FROM product WHERE Тип = «Ноутбук» AND Производитель = pc_product.Производитель )

Ключевые слова SQL SOME | ANY и ALL

Ключевые слова SOME и ANY являются синонимами, поэтому в запросе можно использовать любое из них. Результатом такого запроса будет являться один столбец величин.

Таблица product:для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union
Таблица pc:для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

SELECT DISTINCT Производитель FROM product WHERE Тип = «Компьютер» AND NOT Номер = ANY( SELECT Номер FROM pc )

SELECT DISTINCT Номер, Цена FROM notebook WHERE Цена > ALL ( SELECT цена FROM pc )

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union
Этот запрос корректен по той причине, что скалярное выражение Цена сравнивается с подзапросом, который возвращает единственное значение

Функции работы со строками в SQL

Функция LEFT вырезает слева из строки заданное вторым аргументом число символов:

Функция RIGHT возвращает заданное число символов справа из строкового выражения:

Функция SQL Replace

Функция заменяет в строке1 все вхождения строки2 на строку3. В первую очередь данная функция полезна в операторах обновления таблиц (Update).

Другие строковые функции SQL

отсекает пробелы в начале строки

отсекает пробелы в конце строки

преобразует все символы строки к нижнему регистру

преобразует все символы строки к верхнему регистру

преобразование числа к его строковому представлению

для добавления указанного количества пробелов

SELECT CONCAT(`name`, SPACE( 6 ), CAST(`zarplata` AS DECIMAL ) ) AS «Сведения» FROM `teachers`

Источник

SQL Оператор UNION

SQL UNION

Оператор UNION используется для объединения результирующего набора из двух или более заявлений SELECT.

Синтаксис UNION

Синтаксис UNION ALL

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

Примечание: Имена столбцов в результирующем наборе обычно равны именам столбцов в первом заявлении SELECT в UNION.

Демо база данных

В этом уроке мы будем использовать хорошо известный пример базы данных Northwind.

Ниже приведен выбор из таблицы «Customers»:

CustomerIDCustomerNameContactNameAddressCityPostalCodeCountry
1

Alfreds FutterkisteMaria AndersObere Str. 57Berlin12209Germany2Ana Trujillo Emparedados y heladosAna TrujilloAvda. de la Constitución 2222México D.F.05021Mexico3Antonio Moreno TaqueríaAntonio MorenoMataderos 2312México D.F.05023Mexico

И выбор из таблицы «Suppliers»:

SupplierIDSupplierNameContactNameAddressCityPostalCodeCountry
1Exotic LiquidCharlotte Cooper49 Gilbert St.LondonEC1 4SDUK
2New Orleans Cajun DelightsShelley BurkeP.O. Box 78934New Orleans70117USA
3Grandma Kelly’s HomesteadRegina Murphy707 Oxford Rd.Ann Arbor48104USA

Пример SQL UNION

Следующая инструкция SQL возвращает города (только отдельные значения) как из таблицы «Customers», так и из таблицы «Suppliers»:

Пример

Примечание: Если некоторые клиенты или поставщики имеют один и тот же город, то каждый город будет указан только один раз, поскольку UNION выбирает только различные значения. Используйте UNION ALL, чтобы также выбрать повторяющиеся значения!

Пример SQL UNION ALL

Следующая инструкция SQL возвращает города (также повторяющиеся значения) как из таблицы «Customers», так и из таблицы «Suppliers»:

Пример

Пример SQL UNION с WHERE

Следующая инструкция SQL возвращает немецкие города (только отдельные значения) как из таблицы «Customers», так и из таблицы «Suppliers»:

Пример

Пример SQL UNION ALL с WHERE

Следующая инструкция SQL возвращает немецкие города (также повторяющиеся значения) как из таблицы «Customers», так и из таблицы «Suppliers»:

Пример

Пример UNION другой

Следующая инструкция SQL содержит список всех клиентов и поставщиков:

Пример

Источник

Учебник по языку SQL (DDL, DML) на примере диалекта MS SQL Server. Часть четвертая

Предыдущие части

В данной части мы рассмотрим

Добавим немного новых данных

Для демонстрационных целей добавим несколько отделов и должностей:

JOIN-соединения – операции горизонтального соединения данных

Здесь нам очень пригодится знание структуры БД, т.е. какие в ней есть таблицы, какие данные хранятся в этих таблицах и по каким полям таблицы связаны между собой. Первым делом всегда досконально изучайте структуру БД, т.к. нормальный запрос можно написать только тогда, когда ты знаешь, что откуда берется. У нас структура состоит из 3-х таблиц Employees, Departments и Positions. Приведу здесь диаграмму из первой части:

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

Если суть РДБ – разделяй и властвуй, то суть операций объединений снова склеить разбитые по таблицам данные, т.е. привести их обратно в человеческий вид.

Если говорить просто, то операции горизонтального соединения таблицы с другими таблицами используются для того, чтобы получить из них недостающие данные. Вспомните пример с еженедельным отчетом для директора, когда при запросе из таблицы Employees, нам для получения окончательного результата недоставало поля «Название отдела», которое находится в таблице Departments.

Понимание каждого вида соединения очень важно, т.к. от применения того или иного вида, результат запроса может отличаться. Сравните результаты одного и того же запроса с применением разного типа соединения, попробуйте пока просто увидеть разницу и идите дальше (мы сюда еще вернемся):

IDNameDepartmentIDIDName
1000Иванов И.И.11Администрация
1001Петров П.П.33ИТ
1002Сидоров С.С.22Бухгалтерия
1003Андреев А.А.33ИТ
1004Николаев Н.Н.33ИТ
IDNameDepartmentIDIDName
1000Иванов И.И.11Администрация
1001Петров П.П.33ИТ
1002Сидоров С.С.22Бухгалтерия
1003Андреев А.А.33ИТ
1004Николаев Н.Н.33ИТ
1005Александров А.А.NULLNULLNULL
IDNameDepartmentIDIDName
1000Иванов И.И.11Администрация
1002Сидоров С.С.22Бухгалтерия
1001Петров П.П.33ИТ
1003Андреев А.А.33ИТ
1004Николаев Н.Н.33ИТ
NULLNULLNULL4Маркетинг и реклама
NULLNULLNULL5Логистика
IDNameDepartmentIDIDName
1000Иванов И.И.11Администрация
1001Петров П.П.33ИТ
1002Сидоров С.С.22Бухгалтерия
1003Андреев А.А.33ИТ
1004Николаев Н.Н.33ИТ
1005Александров А.А.NULLNULLNULL
NULLNULLNULL4Маркетинг и реклама
NULLNULLNULL5Логистика
IDNameDepartmentIDIDName
1000Иванов И.И.11Администрация
1001Петров П.П.31Администрация
1002Сидоров С.С.21Администрация
1003Андреев А.А.31Администрация
1004Николаев Н.Н.31Администрация
1005Александров А.А.NULL1Администрация
1000Иванов И.И.12Бухгалтерия
1001Петров П.П.32Бухгалтерия
1002Сидоров С.С.22Бухгалтерия
1003Андреев А.А.32Бухгалтерия
1004Николаев Н.Н.32Бухгалтерия
1005Александров А.А.NULL2Бухгалтерия
1000Иванов И.И.13ИТ
1001Петров П.П.33ИТ
1002Сидоров С.С.23ИТ
1003Андреев А.А.33ИТ
1004Николаев Н.Н.33ИТ
1005Александров А.А.NULL3ИТ
1000Иванов И.И.14Маркетинг и реклама
1001Петров П.П.34Маркетинг и реклама
1002Сидоров С.С.24Маркетинг и реклама
1003Андреев А.А.34Маркетинг и реклама
1004Николаев Н.Н.34Маркетинг и реклама
1005Александров А.А.NULL4Маркетинг и реклама
1000Иванов И.И.15Логистика
1001Петров П.П.35Логистика
1002Сидоров С.С.25Логистика
1003Андреев А.А.35Логистика
1004Николаев Н.Н.35Логистика
1005Александров А.А.NULL5Логистика

Настало время вспомнить про псевдонимы таблиц

Пришло время вспомнить про псевдонимы таблиц, о которых я рассказывал в начале второй части.

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

В нем поля с именами ID и Name есть в обоих таблицах и в Employees, и в Departments. И чтобы их различать, мы предваряем имя поля псевдонимом и точкой, т.е. «emp.ID», «emp.Name», «dep.ID», «dep.Name».

Вспоминаем почему удобнее пользоваться именно короткими псевдонимами – потому что, без псевдонимов наш запрос бы выглядел следующим образом:

По мне, стало очень длинно и хуже читаемо, т.к. имена полей визуально потерялись среди повторяющихся имен таблиц.

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

Только используя псевдонимы, мы сможем осуществить соединения таблицы самой с собой. Предположим встала задача, получить для каждого сотрудника, данные сотрудника, который был принят прямо до него (табельный номер отличается на единицу меньше). Допустим, что у нас табельные номера выдаются последовательно и без дырок, тогда мы можем это сделать примерно следующим образом:

Т.е. здесь одной таблице Employees, мы дали псевдоним «e1», а второй «e2».

Разбираем каждый вид горизонтального соединения

Для этой цели рассмотрим 2 небольшие абстрактные таблицы, которые так и назовем LeftTable и RightTable:

Посмотрим, что в этих таблицах:

LCodeLDescr
1L-1
2L-2
3L-3
5L-5
RCodeRDescr
2B-2
3B-3
4B-4
LCodeLDescrRCodeRDescr
2L-22B-2
3L-33B-3

Здесь были возвращены объединения строк для которых выполнилось условие (l.LCode=r.RCode)

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

LEFT JOIN

LCodeLDescrRCodeRDescr
1L-1NULLNULL
2L-22B-2
3L-33B-3
5L-5NULLNULL

Здесь были возвращены все строки LeftTable, которые были дополнены данными строк из RightTable, для которых выполнилось условие (l.LCode=r.RCode)

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

RIGHT JOIN

LCodeLDescrRCodeRDescr
2L-22B-2
3L-33B-3
NULLNULL4B-4

Здесь были возвращены все строки RightTable, которые были дополнены данными строк из LeftTable, для которых выполнилось условие (l.LCode=r.RCode)

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

По сути если мы переставим LeftTable и RightTable местами, то аналогичный результат мы получим при помощи левого соединения:

LCodeLDescrRCodeRDescr
2L-22B-2
3L-33B-3
NULLNULL4B-4

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

FULL JOIN – это по сути одновременный LEFT JOIN + RIGHT JOIN

LCodeLDescrRCodeRDescr
1L-1NULLNULL
2L-22B-2
3L-33B-3
5L-5NULLNULL
NULLNULL4B-4

Вернулись все строки из LeftTable и RightTable. Строки для которых выполнилось условие (l.LCode=r.RCode) были объединены в одну строку. Отсутствующие в строке данные с левой или правой стороны заполняются NULL-значениями.

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

CROSS JOIN

LCodeLDescrRCodeRDescr
1L-12B-2
2L-22B-2
3L-32B-2
5L-52B-2
1L-13B-3
2L-23B-3
3L-33B-3
5L-53B-3
1L-14B-4
2L-24B-4
3L-34B-4
5L-54B-4

Каждая строка LeftTable соединяется с данными всех строк RightTable.

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

Возвращаемся к таблицам Employees и Departments

Надеюсь вы поняли принцип работы горизонтальных соединений. Если это так, то возвратитесь на начало раздела «JOIN-соединения – операции горизонтального соединения данных» и попробуйте самостоятельно понять примеры с объединением таблиц Employees и Departments, а потом снова возвращайтесь сюда, обсудим это вместе.

Давайте попробуем вместе подвести резюме для каждого запроса:

ЗапросРезюме
По сути данный запрос вернет только сотрудников, у которых указано значение DepartmentID.
Т.е. мы можем использовать данное соединение, в случае, когда нам нужны данные по сотрудникам числящихся за каким-нибудь отделом (без учета внештаткиков).
Вернет всех сотрудников. Для тех сотрудников у которых не указан DepartmentID, поля «dep.ID» и «dep.Name» будут содержать NULL.
Вспоминайте, что NULL значения в случае необходимости можно обработать, например, при помощи ISNULL(dep.Name,’вне штата’).
Этот вид соединения можно использовать, когда нам важно получить данные по всем сотрудникам, например, чтобы получить список для начисления ЗП.
Здесь мы получили дырки слева, т.е. отдел есть, но сотрудников в этом отделе нет.
Такое соединение можно использовать, например, когда нужно выяснить, какие отделы и кем у нас заняты, а какие еще не сформированы. Эту информацию можно использовать для поиска и приема новых работников из которых будет формироваться отдел.
Этот запрос важен, когда нам нужно получить все данные по сотрудникам и все данные по имеющимся отделам. Соответственно получаем дырки (NULL-значения) либо по сотрудникам, либо по отделам (внештатники).
Данный запрос, например, может использоваться в целях проверки, все ли сотрудники сидят в правильных отделах, т.к. может у некоторых сотрудников, которые числятся как внештатники, просто забыли указать отдел.
В таком виде даже сложно придумать где это можно применить, поэтому пример с CROSS JOIN я покажу ниже.

Обратите внимание, что в случае повторения значений DepartmentID в таблице Employees, произошло соединение каждой такой строки со строкой из таблицы Departments с таким же ID, то есть данные Departments объединились со всеми записями для которых выполнилось условие (emp.DepartmentID=dep.ID):

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

В нашем случае все получилось правильно, т.е. мы дополнили таблицу Employees, данными таблицы Departments. Я специально заострил на этом внимание, т.к. бывают случаи, когда такое поведение нам не нужно. Для демонстрации поставим задачу – для каждого отдела вывести последнего принятого сотрудника, если сотрудников нет, то просто вывести название отдела. Возможно напрашивается такое решение – просто взять предыдущий запрос и поменять условие соединение на RIGHT JOIN, плюс переставить поля местами:

IDNameIDName
1Администрация1000Иванов И.И.
2Бухгалтерия1002Сидоров С.С.
3ИТ1001Петров П.П.
3ИТ1003Андреев А.А.
3ИТ1004Николаев Н.Н.
4Маркетинг и рекламаNULLNULL
5ЛогистикаNULLNULL

Но мы для ИТ-отдела получили три строчки, когда нам нужна была только строчка с последним принятым сотрудником, т.е. Николаевым Н.Н.

Задачу такого рода, можно решить, например, при помощи использования подзапроса:

IDNameIDName
1Администрация1000Иванов И.И.
2Бухгалтерия1002Сидоров С.С.
3ИТ1004Николаев Н.Н.
4Маркетинг и рекламаNULLNULL
5ЛогистикаNULLNULL

При помощи предварительного объединения Employees с данными подзапроса, мы смогли оставить только нужных нам для соединения с Departments сотрудников.

Здесь мы плавно переходим к использованию подзапросов. Я думаю использование их в таком виде должно быть для вас понятно на интуитивном уровне. То есть подзапрос подставляется на место таблицы и играет ее роль, ничего сложного. К теме подзапросов мы еще вернемся отдельно.

Посмотрите отдельно, что возвращает подзапрос:

MaxEmployeeID
1005
1000
1002
1004

Т.е. он вернул только идентификаторы последних принятых сотрудников, в разрезе отделов.

Соединения выполняются последовательно сверху-вниз, наращиваясь как снежный ком, который катится с горы. Сначала происходит соединение «Employees emp JOIN (Подзапрос) lastEmp», формируя новый выходной набор:

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

Потом идет объединение набора, полученного «Employees emp JOIN (Подзапрос) lastEmp» (назовем его условно «ПоследнийРезультат») с Departments, т.е. «ПоследнийРезультат RIGHT JOIN Departments dep»:

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

Самостоятельная работа для закрепления материала

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

Для закрепления материала про JOIN-соединения сделаем следующее:

Посмотрим, что в таблицах:

LCodeLDescr
1L-1
2L-2a
2L-2b
3L-3
5L-5
RCodeRDescr
2B-2a
2B-2b
3B-3
4B-4

А теперь попытайтесь сами разобрать, каким образом получилась каждая строчка запроса с каждым видом соединения (Excel вам в помощь):

LCodeLDescrRCodeRDescr
2L-2a2B-2a
2L-2a2B-2b
2L-2b2B-2a
2L-2b2B-2b
3L-33B-3

LCodeLDescrRCodeRDescr
1L-1NULLNULL
2L-2a2B-2a
2L-2a2B-2b
2L-2b2B-2a
2L-2b2B-2b
3L-33B-3
5L-5NULLNULL

LCodeLDescrRCodeRDescr
2L-2a2B-2a
2L-2b2B-2a
2L-2a2B-2b
2L-2b2B-2b
3L-33B-3
NULLNULL4B-4

LCodeLDescrRCodeRDescr
1L-1NULLNULL
2L-2a2B-2a
2L-2a2B-2b
2L-2b2B-2a
2L-2b2B-2b
3L-33B-3
5L-5NULLNULL
NULLNULL4B-4

LCodeLDescrRCodeRDescr
1L-12B-2a
2L-2a2B-2a
2L-2b2B-2a
3L-32B-2a
5L-52B-2a
1L-12B-2b
2L-2a2B-2b
2L-2b2B-2b
3L-32B-2b
5L-52B-2b
1L-13B-3
2L-2a3B-3
2L-2b3B-3
3L-33B-3
5L-53B-3
1L-14B-4
2L-2a4B-4
2L-2b4B-4
3L-34B-4
5L-54B-4

Еще раз про JOIN-соединения

Еще один пример с использованием нескольких последовательных операций соединении. Здесь повтор получился не специально, так получилось – не выбрасывать же материал. 😉 Но ничего «повторение – мать учения».

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

Первым делом выбрались все записи таблицы Employees:

Дальше произошло соединение с таблицей Departments:

Дальше уже идет соединение этого набора с таблицей Positions:

Т.е. это выглядит примерно так:

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

И в последнюю очередь идет возврат тех данных, которые мы просим вывести:

Соответственно, ко всему этому полученному набору можно применить фильтр WHERE и сортировку ORDER BY:

IDEmployeeNamePositionNameDepartmentName
1004Николаев Н.Н.ПрограммистИТ
1001Петров П.П.ПрограммистИТ

То есть последний полученный набор – представляет собой такую же таблицу, над которой можно выполнять базовый запрос:

То есть если раньше в роли источника выступала только одна таблица, то теперь на это место мы просто подставляем наше выражение:

В результате чего получаем тот же самый базовый запрос:

А теперь, применим группировку:

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

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

Обещанный пример с CROSS JOIN

Давайте используем соединение CROSS JOIN, чтобы подсчитать сколько сотрудников, в каком отделе и на каких должностях числится. Для каждого отдела перечислим все существующие должности:

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

В данном случае сначала выполнилось соединение при помощи CROSS JOIN, а затем к полученному набору сделалось соединение с данными из подзапроса при помощи LEFT JOIN. Вместо таблицы в LEFT JOIN мы использовали подзапрос.

Подзапрос заключается в скобки и ему присваивается псевдоним, в данном случае это «e». То есть в данном случае объединение происходит не с таблицей, а с результатом следующего запроса:

DepartmentIDPositionIDEmplCount
NULLNULL1
211
121
332
341

Вместе с псевдонимом «e» мы можем использовать имена DepartmentID, PositionID и EmplCount. По сути дальше подзапрос ведет себя так же, как если на его месте стояла таблица. Соответственно, как и у таблицы,
все имена колонок, которые возвращает подзапрос, должны быть заданы явно и не должны повторяться.

Связь при помощи WHERE-условия

Для примера перепишем следующий запрос с JOIN-соединением:

Через WHERE-условие он примет следующую форму:

Здесь плохо то, что происходит смешивание условий соединения таблиц (emp.DepartmentID=dep.ID) с условием фильтрации (emp.DepartmentID=3).

Теперь посмотрим, как сделать CROSS JOIN:

Через WHERE-условие он примет следующую форму:

Т.е. в этом случае мы просто не указали условие соединения таблиц Employees и Departments. Чем плох этот запрос? Представьте, что кто-то другой смотрит на ваш запрос и думает «кажется тот, кто писал запрос забыл здесь дописать условие (emp.DepartmentID=dep.ID)» и с радостью, что обнаружил косяк, дописывает это условие. В результате чего задуманное вами может сломаться, т.к. вы подразумевали CROSS JOIN. Так что, если вы делаете декартово соединение, то лучше явно укажите, что это именно оно, используя конструкцию CROSS JOIN.

Для оптимизатора запроса может быть и без разницы как вы реализуете соединение (при помощи WHERE или JOIN), он их может выполнить абсолютно одинаково. Но из соображения понимаемости кода, я бы рекомендовал в современных СУБД стараться никогда не делать соединение таблиц при помощи WHERE-условия. Использовать WHERE-условия для соединения, в том случае, если в СУБД реализованы конструкции JOIN, я бы назвал сейчас моветоном. WHERE-условия служат для фильтрации набора, и не нужно перемешивать условия служащие для соединения, с условиями отвечающими за фильтрацию. Но если вы пришли к выводу, что без реализации соединения через WHERE не обойтись, то конечно приоритет за решеной задачей и «к черту все устои».

UNION-объединения – операции вертикального объединения результатов запросов

Я специально использую словосочетания горизонтальное соединение и вертикальное объединение, т.к. заметил, что новички часто недопонимают и путают суть этих операций.

Давайте первым делом вспомним как мы делали первую версию отчета для директора:

Так вот, если бы мы не знали, что существует операция группировки, но знали бы, что существует операция объединения результатов запроса при помощи UNION ALL, то мы могли бы склеить все эти запросы следующим образом:

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

Т.е. UNION ALL позволяет склеить результаты, полученные разными запросами в один общий результат.

Соответственно количество колонок в каждом запросе должно быть одинаковым, а также должны быть совместимыми и типы этих колонок, т.е. строка под строкой, число под числом, дата под датой и т.п.

Немного теории

В MS SQL реализованы следующие виды вертикального объединения:

ОперацияОписание
UNION ALLВ результат включаются все строки из обоих наборов. (A+B)
UNIONВ результат включаются только уникальные строки двух наборов. DISTINCT(A+B)
EXCEPTВ результат попадают уникальные строки верхнего набора, которые отсутствуют в нижнем наборе. Разница 2-х множеств. DISTINCT(A-B)
INTERSECTВ результат включаются только уникальные строки, присутствующие в обоих наборах. Пересечение 2-х множеств. DISTINCT(A&B)

Все это проще понять на наглядном примере.

Создадим 2 таблицы и наполним их данными:

Посмотрим на содержимое:

T1T2
1Text 1
1Text 1
2Text 2
3Text 3
4Text 4
5Text 5
B1B2
2Text 2
3Text 3
6Text 6
6Text 6

UNION ALL

для чего нужен оператор union. Смотреть фото для чего нужен оператор union. Смотреть картинку для чего нужен оператор union. Картинка про для чего нужен оператор union. Фото для чего нужен оператор union

UNION

По сути UNION можно представить, как UNION ALL, к которому применена операция DISTINCT:

Источник

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

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