Windows. Вирусы. Ноутбуки. Интернет. Office. Утилиты. Драйверы

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

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

Запросы в языке SQL комбинируются с помощью оператора UNION . Для этого необходимо указать каждый запрос SELECT и разместить между ними ключевое слово UNION . Ограничений по количеству использованного оператора UNION в одном общем запросе нет. В предыдущем разделе мы отмечали, что Access не имеет возможности создавать полное внешнее объединение , теперь мы посмотрим, как можно этого достичь через оператор UNION .

SELECT *
FROM Sumproduct LEFT JOIN Sellers ON Sumproduct.City = Sellers.City
UNION
SELECT *

FROM Sumproduct RIGHT JOIN Sellers ON Sumproduct.City = Sellers.City

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

Также стоит отметить, что во многих случаях вместо UNION мы можем использовать предложение WHERE со многими условиями, и получать аналогичный результат. Однако из-за UNION записи выглядят более лаконичными и понятными. Также необходимо соблюдать определенные правила при написании комбинированных запросов:

  • запрос UNION должен включать два и более операторов SELECT , отделенных между собой ключевым словом UNION (т.е. если в запросе используется четыре оператора SELECT, то должно быть три ключевых слова UNION)
  • каждый запрос в операторе UNION должен иметь одни и те же столбцы, выражения или статистические функции, которые, к тому же, должны быть перечислены в одинаковом порядке
  • типы данных столбцов должны быть совместимыми. Они не обязательно должны быть одного типа, однако обязаны иметь подобный тип, чтобы СУБД могла их однозначно преобразовать (например, это могут быть различные числовые типы данных или различные типы даты).

2. Включение или выключение повторяющихся строк

Запрос с UNION автоматически удаляет все повторяющиеся строки из набора результатов запроса (то есть, ведет себя как предложения WHERE с несколькими условиями в одном операторе SELECT ). Такое поведение оператора UNION по умолчанию, но при желании мы можем изменить это. Для этого нам следует использовать оператор UNION ALL вместо UNION .

3. Сортировка результатов комбинированных запросов

Результаты выполнения оператора SELECT сортируются с помощью предложения ORDER BY . При комбинировании запросов с помощью UNION только одно предложение ORDER BY может быть использовано, и оно должно быть проставлено в последнем операторе SELECT . Действительно, на практике нет особого смысла часть результатов сортировать в одном порядке, а другую часть - в другом. Поэтому несколько предложений ORDER BY применять не разрешается.

Оператор языка SQL UNION предназначен для объединения результирующих таблиц базы данных, полученных с применением слова SELECT. Условие объединения результирующих таблиц: совпадение числа, порядка следования и типа данных столбцов. ORDER BY следует применять к результату объединения и размещать только в конце составного запроса. Оператор UNION имеет следующий синтаксис:

SELECT ИМЕНА_СТОЛБЦОВ (1..N) FROM ИМЯ_ТАБЛИЦЫ UNION SELECT ИМЕНА_СТОЛБЦОВ (1..N) FROM ИМЯ_ТАБЛИЦЫ

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

При использовании оператора UNION без слова ALL результат не содержит дубликатов, а со словом ALL - содержит дубликаты.

Итоги и индивидуальные значения в одной таблице с помощью оператора SQL UNION

Одним запросом можно вывести из таблицы индивидуальные значения столбцов, например, число лет, проработанных сотрудниками фирмы, размеры их заработной платы и другие. Другим запросом - с использованием агрегатных функций - можно получить, например, сумму заработных плат, получаемых сотрудниками отделов или занимающих те или иные должности, или среднее число лет трудового стажа (в таких запросах применяется группировка с помощью оператора GROUP BY).

А если нам требуется получить в одной таблице и сводку всех индивидуальных значений, и итоговые значения? Здесь на помощь приходит оператор SQL UNION, с помощью которого два запроса объединяются. К результату объединения требуется применить упорядочение, используя оператор ORDER BY. Для чего это необходимо, будет лучше понятно из примеров.

Пример 1. В базе данных фирмы есть таблица Staff, содержащая данные о сотрудниках фирмы. В ней есть столбцы Salary (размер заработной платы), Job (должность) и Years (длительность трудового стажа). Первый запрос возвращает индивидуальные размеры заработной платы, упорядоченные по должностям:

SELECT Name, Job, Salary FROM STAFF ORDER BY Job

Name Job Salary
Sanders Mgr 18357.5
Marenghi Mgr 17506.8
Pernal Sales 18171.2
Doctor Sales 12322.4
Factor Sales 16228.7

Второй запрос вернёт суммарную заработную плату по должностям. Мы уже готовим этот запрос для соединения с первым, поэтому будем помнить, что условием соединения является равное число столбцов, совпадение их названий, порядка следования и типов данных. Поэтому включаем в таблицу с итогами также столбец Name с произвольным значением "Z-TOTAL":

SELECT "Z-TOTAL" AS Name, Job, SUM (Salary) AS Salary FROM STAFF GROUP BY Job

Результатом выполнения запроса будет следующая таблица:

Name Job Salary
Z-TOTAL Mgr 35864.3
Z-TOTAL Sales 46722.3

Теперь объединим запросы при помощи оператора UNION и применим оператору ORDER BY к результату объединения. Группировать следует по двум столбцам: должность (Job) и имя (Name), чтобы строки с итоговыми (суммарными) значениями, в которых значение имени - "Z-TOTAL", находились ниже строк с индивидуальными значениями. Объединение результатов запросов будет следующим:

(SELECT Name, Job, Salary FROM STAFF ) UNION (SELECT "Z-TOTAL" AS Name, Job, SUM (Salary) AS Salary FROM STAFF GROUP BY Job) ORDER BY Job, Name

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

Name Job Salary
Marenghi Mgr 17506.8
Sanders Mgr 18357.5
Z-TOTAL Mgr 35864.3
Doctor Sales 12322.4
Factor Sales 16228.7
Pernal Sales 18171.2
Z-TOTAL Sales 46722.3

Написать запросы с использованием UNION самостоятельно, а затем посмотреть решение

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

Пример 3. В базе данных фирмы есть таблица Staff, содержащая данные о сотрудниках фирмы. В ней есть столбцы Name (фамилия), Dept (номер отдела), и Years (длительность трудового стажа).

Name Dept Years
Sanders 20 7
Pernal 20 8
Marenghi 38 5
Doctor 20 5
Factor 38 8

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

Другие случаи объединения запросов к одной таблице с помощью оператора SQL UNION

Пример 4. В базе данных фирмы есть таблица Staff, содержащая данные о сотрудниках фирмы. В ней есть столбцы Salary (размер заработной платы), Job (должность) и Years (длительность трудового стажа). Первый запрос нужен для получения данных о сотрудниках, заработная плата которых более 21000:

Результатом выполнения запроса будет следующая таблица:

Теперь требуются данные, в которых объединены критерии отбора, применённые в двух запросах. Объединяем запросы при помощи оператора UNION:

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

ID Name
10 Sanders
30 Marenghi
100 Plotz
140 Fraye
160 Molinare
240 Daniels
260 Jones

Запрос с оператором UNION может возвращать и большее количество столбцов, важно, повторимся, чтобы в объединяемых запросах число столбцов, порядок их следования и типы данных совпадали.

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

Результатом выполнения запроса будет следующая таблица:

Результатом выполнения запроса будет следующая таблица:

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

Результатом выполнения запроса будет следующая таблица:

Объединение результатов запросов к двум таблицам с помощью оператора SQL UNION

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

Пример 6. Есть база данных склада строительных материалов. В ней есть таблицы, содержащая данные об обоях. Таблица Vinil содержит данные о виниловых обоях, таблица Paper - о бумажных обоях. Требуется узнать данные о ценах обоев из одной и другой таблицы.

Чтобы извлечь не повторяющиеся данные о ценах на виниловые обои, составим запрос со словом DISTINCT:

SELECT DISTINCT Price FROM VINIL

Результатом выполнения запроса будет следующая таблица:

Теперь составим объединённый запрос с оператором UNION:

SELECT DISTINCT Price FROM VINIL UNION SELECT DISTINCT Price FROM PAPER

Так как мы не используем слово ALL, дубликаты значений 400, 500 и 530 выводиться не будут. Результатом выполнения запроса будет следующая таблица:

Price
300
320
360
400
430
500
530
610
720
800
850

Пример 7. База данных и таблицы - те же, что и в предыдущем примере.

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

SELECT DISTINCT Price FROM VINIL UNION ALL SELECT DISTINCT Price FROM PAPER

Результатом выполнения запроса будет следующая таблица:

Price
300
320
360
400
400
430
500
500
530
530
610
720
800
850

При помощи оператора SQL UNION можно объединить как простые запросы, так и запросы, содержащие подзапросы (вложенные запросы) . Рассмотрим соответствующий пример.

Пример 8. Есть база данных "Театр". В её таблице Play содержатся данные о постановках (названия - в столбце Name), в таблице Director - даные о режиссёрах (в столбце Fname - имя, в столбце Lname - фамилия). Первичный ключ таблицы Director - dir_id - идентификационный номер режиссёра. Dir_id также - внешний ключ таблицы Play, он ссылается на первичный ключ таблицы Director. Требуется вывести спектакли режиссеров John Barton и Trevor Nunn.

Решение. Объединим результаты двух запросов - один возвращает спектакли режиссёра John Barton, другой - режиссёра Trevor Nunn. А каждый из этих объединяемых запросов к таблице Play делаем с подзапросом к таблице Director, который возвращает dir_id по имени и фамилии режиссёра. Каждый внешний запрос принимает из вложенного запроса значение ключа dir_id и возвращает названия постановок (Name):

Реляционные базы данных и язык SQL

Синтаксис

Оператор указывается между запросами. В упрощенном виде это выглядит следующим образом:

< запрос1 > UNION [ ALL ] < запрос2 > UNION [ ALL ] < запрос3 > ..... ;

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

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

Правила использования

Существуют два основных правила, регламентирующие порядок использования оператора UNION:

  • Число и порядок извлекаемых столбцов должны совпадать во всех объединяемых запросах;
  • Типы данных в соответствующих столбцах должны быть совместимы.

Определения столбцов, данные из которых извлекаются в объединяемых запросах, не должны совпадать, однако должны быть совместимыми путем неявного преобразования. Если типы данных различаются, то получившийся тип данных определяется на основе правил очередности типов данных (для конкретной СУБД). Если типы совпадают, но различаются в точности, масштабе или длине, результат определяется на основе правил, используемых для объединения выражений (для конкретной СУБД) . Типы не определенные ANSI, такие как DATA и BINARY, обычно должны совпадать с другими столбцами такого же нестандартного типа .

Еще одно ограничение на совместимость - это запрет пустых значений (NULL) в любом столбце объединения, причем эти значения необходимо запретить и для всех соответствующих столбцов в других запросах объединения, поскольку пустые значения (NULL) запрещены с ограничением NOT NULL. Кроме того, нельзя использовать UNION в подзапросах, а также нельзя использовать агрегатные функции в предложении SELECT запроса в объединении (однако большинство СУБД пренебрегают этими ограничениями) .

Применение

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

Также стоит отметить, что UNION ALL работает быстрее, чем просто UNION , поскольку по умолчанию при использовании оператора UNION проводится дополнительная фильтрация результата аналогичная SELECT DISTINCT , а при использовании UNION ALL - нет .

Примеры

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

Даны две таблицы:

При выполнении следующего запроса:

(SELECT * FROM sales2005) UNION (SELECT * FROM sales2006) ;

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

В результате отобразятся две строки с Иваном, так как эти строки различаются значениями в столбцах. Но при этом в результате присутствует лишь одна строка с Алексеем, поскольку значения в столбцах полностью совпадают.

Использование UNION ALL при выборке из двух таблиц

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

(SELECT * FROM sales2005) UNION ALL (SELECT * FROM sales2006) ;

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

Использование UNION при выборке из одной таблицы

Аналогичным образом можно объединять два разных запроса из одной и той же таблицы (хотя вместо этого, как правило, необходимые параметры комбинируют в одном запросе при помощи ключевых слов AND и OR в условии WHERE):

В результате получится:

person amount
Иван 1000
Сергей 5000

Использование UNION как внешнее объединение

При помощи UNION можно создавать также полные внешние объединения (иногда используется в случае отсутствия встроенной прямой поддержки внешних объединений):

(SELECT * FROM employee LEFT JOIN department ON employee. DepartmentID = department. DepartmentID) UNION (SELECT * FROM employee RIGHT JOIN department ON employee. DepartmentID = department. DepartmentID) ;

Но при этом необходимо помнить, что это все же не одно и то же, что и оператор JOIN .

См. также

Примечания

Ссылки

Общее описание
  • Понимание SQL. Глава 14. Использование предложения UNION (рус.)
  • SQL UNION Operator (англ.)
  • UNION (DISTINCT) and UNION ALL (англ.)
Реализация в MS SQL Server
  • Описание UNION (Transact-SQL) в MSDN (рус.)
Реализация в MySQL
  • Querying data by using SQL UNION (примеры использования в MySQL) (англ.)
  • UNION Syntax (в MySQL) (англ.)
Реализация в PostgreSQL
  • UNION Clause (в PostgreSQL) (англ.)
Реализация в Oracle
  • The UNION (ALL), INTERSECT, MINUS Operators (англ.)
Реализация в Informix
  • Compose advanced SELECT statements (англ.)

Пришло время поговорить об объединении данных по средствам конструкции union и union all , так как это иногда бывает очень полезно, и без использования такой конструкции бывает порой не обойтись. Примеры будем писать в СУБД MSSQL 2008 , используя язык SQL.

И начать хотелось бы с того, что мы с Вами уже рассматривали много примеров написания запросов на SQL , например, оператор select языка SQL , или использование строковых функций SQL , также рассматривали программирование как на plpgsql так и на transact-sql, например, Как написать функцию на PL/pgSQL и Transact-sql – Табличные функции и временные таблицы соответственно.

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

И так приступим. И для начала давайте рассмотрим, что же это за операторы union и union all.

Что такое UNION и UNION ALL в SQL?

  • UNION – это оператор SQL для объединения результирующего набора данных нескольких запросов, и данный оператор выводит только уникальные строки в запросах, т.е. например, Вы объединяете два запроса и в каждом из которых есть одинаковые данные, другими словами полностью идентичные, и оператор union объединит их в одну строку для того чтобы не было дублей;
  • UNION ALL – это оператор SQL для объединения результирующего набора данных нескольких запросов, а вот данный оператор, выведет уже абсолютно все строки, даже дубли.

Необходимые условия для операторов union и union all

  1. Набор полей должен быть одинаковый во всех запросах, т.е. количество полей в каждом запросе, который будет объединяться по средствам конструкции union или union all, должно быть одинаковое;
  2. Типы данных полей также должны совпадать в каждом запросе, т.е. например, если Вы захотите написать один запрос, в котором будет тип данных int а во втором запросе тип данных varchar то у Вас запрос не выполнится а окно запроса выведет ошибку;
  3. В случае сортировки оператор order by можно указать только после последнего запроса .

Теперь давайте поговорим о том, в каких случаях нам может понадобиться использование этих операторов. Ну, например, у Вас есть несколько баз со схожей структурой, каждая из которых создана, например, для какого-нибудь филиала, а Вам необходимо объединить эти данные для предоставления отчетности по всем филиалам руководству и самое простое как это можно сделать, это написать запросы на SQL, каждый из которых будет обращаться к разным базам, и через конструкцию union или union all объединить их. Также иногда бывает необходимо объединить данные в одной базе таким образом, что обычными объединениями это не реализовать и приходится использовать union. Почему я говорю «приходится» да потому что данная конструкция значительно увеличивает время выполнения запроса, если например данных очень много, и злоупотреблять ею не нужно.

Хватит теории, переходим к практике.

Примечание! Как уже говорилось, запросы будем писать в Management Studio для SQL Server 2008

Примеры использования union и union all

Для начала создадим две простых таблицы test_table и test_table_2

CREATE TABLE ( IDENTITY(1,1) NOT NULL, (18, 0) NULL, (50) NULL, CONSTRAINT PRIMARY KEY CLUSTERED ( ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ) ON GO SET ANSI_PADDING OFF GO --и вторая таблица CREATE TABLE ( IDENTITY(1,1) NOT NULL, (18, 0) NULL, (50) NULL, CONSTRAINT PRIMARY KEY CLUSTERED ( ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ) ON GO SET ANSI_PADDING OFF GO

Они одинаковые для примера, только разные названия. Я заполнил их вот такими данными:

Теперь давайте напишем запрос, который объединит результирующие данные в одни, например через union. Синтаксис очень прост:

Запрос 1 union Запрос 2 union Запрос 3 и т.д.

Вот запрос:

Select number, text from test_table union select number, text from test_table_2

Как Вы видите, вывелось всего 5 строк, так как у нас первая строка в первом запросе и первая строка во втором запросе одинаковые, поэтому они объединились.

Теперь давайте объединим через union all

Вот запрос:

Select number, text from test_table union all select number, text from test_table_2

Здесь уже вывелись все строки, так как мы указали union all.

А теперь давайте рассмотрим, какие могут быть ошибки даже в этом простом запросе. Например, мы перепутали последовательность полей:

Или мы в первом запросе указали дополнительное поле, а во втором этого не сделали.

Также, например, при использовании order by:

Здесь мы указали сортировку в каждом запросе, а нужно было только в последнем, например:

Select number, text from test_table union all select number, text from test_table_2 order by number

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

Select id ,number, text from test_table union all select "", number, text from test_table_2

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

Наверное, все, что я хотел рассказать о конструкции union и union all языка SQL я рассказал, если есть вопросы по использованию этих операторов, задавайте их в комментариях. Удачи!

Если заметили ошибку, выделите фрагмент текста и нажмите Ctrl+Enter
ПОДЕЛИТЬСЯ: