Union (SQL)

Поделись знанием:
Перейти к: навигация, поиск

В языке SQL ключевое слово UNION применяется для объединения результатов двух SQL-запросов в единую таблицу, состоящую из схожих строк. Оба запроса должны возвращать одинаковое число столбцов и совместимые типы данных в соответствующих столбцах. Данный оператор был описан в первом стандарте SQL — SQL/89[1].





Синтаксис

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

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

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

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

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

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

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

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

В Microsoft SQL Server столбцы с типом данных XML должны быть эквивалентными. Все столбцы должны либо иметь тип, определенный в XML-схеме, либо быть нетипизированными. Типизированные столбцы должны относиться к одной и той же коллекции XML-схем[2].

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

Применение

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

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

Примеры

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

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

sales2005
person amount
Иван 1000
Алексей 2000
Сергей 5000
sales2006
person amount
Иван 2000
Алексей 2000
Петр 35000

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

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

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

person amount
Иван 1000
Алексей 2000
Иван 2000
Сергей 5000
Петр 35000

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

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

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

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

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

person amount
Иван 1000
Иван 2000
Алексей 2000
Алексей 2000
Сергей 5000
Петр 35000

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

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

(SELECT person, amount FROM sales2005 WHERE amount=1000)
UNION
(SELECT person, amount FROM sales2005 WHERE person like 'Сергей');

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

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.

См. также

Напишите отзыв о статье "Union (SQL)"

Примечания

  1. [www.interface.ru/fset.asp?Url=/misc/sql/sql3.htm Язык баз данных SQL/89]  (рус.)
  2. 1 2 [msdn.microsoft.com/ru-ru/library/ms180026.aspx UNION (Transact-SQL)]  (рус.)
  3. 1 2 [www.sql.ru/docs/sql/u_sql/ch14.shtml Использование предложения UNION]  (рус.)
  4. [sql-tips.by.ru/tips_tsql.htm Оптимизация запросов]  (рус.)

Пункт 4 - нерабочая ссылка (на 08.11.2012)

Ссылки

Общее описание
  • [www.sql.ru/docs/sql/u_sql/ch14.shtml Понимание SQL. Глава 14. Использование предложения UNION]  (рус.)
  • [www.w3schools.com/sql/sql_union.asp SQL UNION Operator]  (англ.)
  • [www.gplivna.eu/papers/sql_set_operators.htm#p2.3 UNION (DISTINCT) and UNION ALL]  (англ.)
Реализация в MS SQL Server
  • [msdn.microsoft.com/ru-ru/library/ms180026.aspx Описание UNION (Transact-SQL) в MSDN]  (рус.)
Реализация в MySQL
  • [www.mysqltutorial.org/sql-union-mysql.aspx Querying data by using SQL UNION] (примеры использования в MySQL)  (англ.)
  • [dev.mysql.com/doc/refman/5.0/en/union.html UNION Syntax] (в MySQL)  (англ.)
Реализация в PostgreSQL
  • [www.postgresql.org/docs/current/static/sql-select.html#SQL-UNION UNION Clause] (в PostgreSQL)  (англ.)
Реализация в Oracle
  • [download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries004.htm The UNION (ALL), INTERSECT, MINUS Operators]  (англ.)
Реализация в Informix
  • [publib.boulder.ibm.com/infocenter/idshelp/v115/topic/com.ibm.sqlt.doc/ids_sqt_192.htm Compose advanced SELECT statements]  (англ.)

Отрывок, характеризующий Union (SQL)

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


Главное действие Бородинского сражения произошло на пространстве тысячи сажен между Бородиным и флешами Багратиона. (Вне этого пространства с одной стороны была сделана русскими в половине дня демонстрация кавалерией Уварова, с другой стороны, за Утицей, было столкновение Понятовского с Тучковым; но это были два отдельные и слабые действия в сравнении с тем, что происходило в середине поля сражения.) На поле между Бородиным и флешами, у леса, на открытом и видном с обеих сторон протяжении, произошло главное действие сражения, самым простым, бесхитростным образом.
Сражение началось канонадой с обеих сторон из нескольких сотен орудий.
Потом, когда дым застлал все поле, в этом дыму двинулись (со стороны французов) справа две дивизии, Дессе и Компана, на флеши, и слева полки вице короля на Бородино.
От Шевардинского редута, на котором стоял Наполеон, флеши находились на расстоянии версты, а Бородино более чем в двух верстах расстояния по прямой линии, и поэтому Наполеон не мог видеть того, что происходило там, тем более что дым, сливаясь с туманом, скрывал всю местность. Солдаты дивизии Дессе, направленные на флеши, были видны только до тех пор, пока они не спустились под овраг, отделявший их от флеш. Как скоро они спустились в овраг, дым выстрелов орудийных и ружейных на флешах стал так густ, что застлал весь подъем той стороны оврага. Сквозь дым мелькало там что то черное – вероятно, люди, и иногда блеск штыков. Но двигались ли они или стояли, были ли это французы или русские, нельзя было видеть с Шевардинского редута.
Солнце взошло светло и било косыми лучами прямо в лицо Наполеона, смотревшего из под руки на флеши. Дым стлался перед флешами, и то казалось, что дым двигался, то казалось, что войска двигались. Слышны были иногда из за выстрелов крики людей, но нельзя было знать, что они там делали.
Наполеон, стоя на кургане, смотрел в трубу, и в маленький круг трубы он видел дым и людей, иногда своих, иногда русских; но где было то, что он видел, он не знал, когда смотрел опять простым глазом.
Он сошел с кургана и стал взад и вперед ходить перед ним.
Изредка он останавливался, прислушивался к выстрелам и вглядывался в поле сражения.
Не только с того места внизу, где он стоял, не только с кургана, на котором стояли теперь некоторые его генералы, но и с самых флешей, на которых находились теперь вместе и попеременно то русские, то французские, мертвые, раненые и живые, испуганные или обезумевшие солдаты, нельзя было понять того, что делалось на этом месте. В продолжение нескольких часов на этом месте, среди неумолкаемой стрельбы, ружейной и пушечной, то появлялись одни русские, то одни французские, то пехотные, то кавалерийские солдаты; появлялись, падали, стреляли, сталкивались, не зная, что делать друг с другом, кричали и бежали назад.
С поля сражения беспрестанно прискакивали к Наполеону его посланные адъютанты и ординарцы его маршалов с докладами о ходе дела; но все эти доклады были ложны: и потому, что в жару сражения невозможно сказать, что происходит в данную минуту, и потому, что многие адъютапты не доезжали до настоящего места сражения, а передавали то, что они слышали от других; и еще потому, что пока проезжал адъютант те две три версты, которые отделяли его от Наполеона, обстоятельства изменялись и известие, которое он вез, уже становилось неверно. Так от вице короля прискакал адъютант с известием, что Бородино занято и мост на Колоче в руках французов. Адъютант спрашивал у Наполеона, прикажет ли он пореходить войскам? Наполеон приказал выстроиться на той стороне и ждать; но не только в то время как Наполеон отдавал это приказание, но даже когда адъютант только что отъехал от Бородина, мост уже был отбит и сожжен русскими, в той самой схватке, в которой участвовал Пьер в самом начале сраженья.
Прискакавший с флеш с бледным испуганным лицом адъютант донес Наполеону, что атака отбита и что Компан ранен и Даву убит, а между тем флеши были заняты другой частью войск, в то время как адъютанту говорили, что французы были отбиты, и Даву был жив и только слегка контужен. Соображаясь с таковыми необходимо ложными донесениями, Наполеон делал свои распоряжения, которые или уже были исполнены прежде, чем он делал их, или же не могли быть и не были исполняемы.
Маршалы и генералы, находившиеся в более близком расстоянии от поля сражения, но так же, как и Наполеон, не участвовавшие в самом сражении и только изредка заезжавшие под огонь пуль, не спрашиваясь Наполеона, делали свои распоряжения и отдавали свои приказания о том, куда и откуда стрелять, и куда скакать конным, и куда бежать пешим солдатам. Но даже и их распоряжения, точно так же как распоряжения Наполеона, точно так же в самой малой степени и редко приводились в исполнение. Большей частью выходило противное тому, что они приказывали. Солдаты, которым велено было идти вперед, подпав под картечный выстрел, бежали назад; солдаты, которым велено было стоять на месте, вдруг, видя против себя неожиданно показавшихся русских, иногда бежали назад, иногда бросались вперед, и конница скакала без приказания догонять бегущих русских. Так, два полка кавалерии поскакали через Семеновский овраг и только что въехали на гору, повернулись и во весь дух поскакали назад. Так же двигались и пехотные солдаты, иногда забегая совсем не туда, куда им велено было. Все распоряжение о том, куда и когда подвинуть пушки, когда послать пеших солдат – стрелять, когда конных – топтать русских пеших, – все эти распоряжения делали сами ближайшие начальники частей, бывшие в рядах, не спрашиваясь даже Нея, Даву и Мюрата, не только Наполеона. Они не боялись взыскания за неисполнение приказания или за самовольное распоряжение, потому что в сражении дело касается самого дорогого для человека – собственной жизни, и иногда кажется, что спасение заключается в бегстве назад, иногда в бегстве вперед, и сообразно с настроением минуты поступали эти люди, находившиеся в самом пылу сражения. В сущности же, все эти движения вперед и назад не облегчали и не изменяли положения войск. Все их набегания и наскакивания друг на друга почти не производили им вреда, а вред, смерть и увечья наносили ядра и пули, летавшие везде по тому пространству, по которому метались эти люди. Как только эти люди выходили из того пространства, по которому летали ядра и пули, так их тотчас же стоявшие сзади начальники формировали, подчиняли дисциплине и под влиянием этой дисциплины вводили опять в область огня, в которой они опять (под влиянием страха смерти) теряли дисциплину и метались по случайному настроению толпы.