Лекция 14: Извлечение данных при помощи Transact-SQL
Операция UNION
UNION считается не предложением (clause), а операцией (operator). Она используется для объединения результатов двух или нескольких запросов в один набор результатов. Применяя UNION, вы должны соблюдать два следующих правила:
- все запросы должны иметь одинаковое количество колонок;
- типы данных соответственных колонок из запросов должны быть совместимыми.
Колонки, перечисленные в операторах SELECT, объединенные при помощи UNION, сопоставляются друг с другом следующим образом: первая колонка из первого оператора SELECT будет соответствовать первым колонкам из всех последующих операторов SELECT, вторая колонка будет соответствовать вторым колонкам из всех последующих операторов SELECT, и т.д. Поэтому во всех операторах SELECT, объединенных при помощи UNION, должно быть одинаковое количество колонок, что гарантирует однозначное сопоставление.
Кроме того, соответственные колонки должны иметь совместимые типы данных. Это значит, что соответственные колонки должны иметь либо одинаковые типы данных, либо SQL Server сможет выполнить неявное преобразование одного типа данных в другой. Ниже дан пример применения операции UNION, соединяющей наборы результатов двух операторов SELECT, выдающих колонки city и state из обеих таблиц publishers и stores:
SELECT city, state FROM publishers UNION SELECT city, state FROM stores GO
Набор результатов (14 строк) будет таким:
city state ------------------------- Fremont CA Los Gatos CA Portland OR Remulade WA Seattle WA Tustin CA Chicago IL Dallas TX Munchen NULL Boston MA New York NY Paris NULL Berkeley CA Washington DC
Две эти колонки, city и state, в обеих таблицах имеют одинаковый тип данных (char), поэтому преобразование типа не потребуется. Заголовки колонок для набора результатов операции UNION берутся из первого оператора SELECT. Если вы хотите создать алиас для заголовка, то поместите его в первый оператор SELECT, вот так:
SELECT city AS "Все города", state AS "Все штаты" FROM publishers UNION SELECT city, state FROM stores GO
Набор результатов (14 строк) будет таким:
Все города Все штаты ------------------------------------ Fremont CA Los Gatos CA Portland OR Remulade WA Seattle WA Tustin CA Chicago IL Dallas TX Munchen NULL Boston MA New York NY Paris NULL Berkeley CA Washington DC
При объединении наборов результатов вовсе не обязательно указывать в обоих предложениях SELECT одни и те же колонки. Например, вы можете выбрать колонки city и state из таблицы stores и колонки city и country из таблицы publishers, вот так:
SELECT city, country FROM publishers UNION SELECT city, state FROM stores GO
Набор результатов (14 строк) будет таким:
city country ---------------------------- Fremont CA Los Gatos CA Portland OR Remulade WA Seattle WA Tustin CA New York USA Paris France Boston USA Munchen Germany Washington USA Chicago USA Berkeley USA Dallas USA
В этом наборе результатов верхние шесть строк берутся из набора результатов запроса, применяемого к таблице stores, а последние восемь строк берутся из набора результатов запроса, применяемого к таблице publishers. Колонка state имеет тип данных char, а колонка country имеет тип данных varchar. Так как два этих типа данных являются совместимыми, то SQL Server выполнит неявное преобразование таким образом, чтобы обе колонки стали иметь тип varchar. Колонки итогового набора результатов имеют заголовки city и country, так, как указано в первом операторе SELECT, но здесь было бы лучше, чтобы вторая колонка имела заголовок не country (страна), а State or Country (штат или страна).
Единственное ключевое слово, которое можно применять вместе с UNION – это необязательное ключевое слово ALL. Если вы примените его, то в набор результатов будут включены также все повторяющиеся строки (другими словами, в набор результатов будут включены полностью все строки). Если ключевое слово ALL не применяется, то по умолчанию из набора результатов будут исключены все дублирующиеся строки.
ORDER BY можно применять не в каждом операторе SELECT объединения, а только в самом последнем. Благодаря этому ограничению, итоговый набор результатов будет отсортирован только один раз сразу для всех результатов. С другой стороны, вы можете применять GROUP BY и HAVING в отдельных операторах, так как они влияют только на отдельные наборы результатов, а не на итоговый набор результатов. Ниже приведен пример, иллюстрирующий объединение результатов двух операторов SELECT, каждый из которых имеет предложение GROUP BY:
SELECT type, COUNT(title) AS "Number of Titles" FROM titles GROUP BY type UNION SELECT pub_name, COUNT(titles.title) FROM publishers, titles WHERE publishers.pub_id = titles.pub_id GROUP BY pub_name GO
Набор результатов (9 строк) будет таким:
type Number of Titles ———————————————————— ———————— Algodata Infosystems 6 Binnet & Hardley 7 New Moon Books 5 psychology 5 mod_cook 2 trad_cook 3 popular_comp 3 UNDECIDED 1 business 4
Этот набор результатов показывает, сколько различных названий книг было опубликовано каждым из издателей, публиковавших книги (первые три строки набора результатов) и количество названий книг для каждой из категорий. Каждое из предложений GROUP BY выполняется только на своем подзапросе.
Операцию UNION можно применять и более чем для двух операторов SELECT. Создавая объединение, не забывайте следить, чтобы все колонки и типы данных в запросах были взаимно согласованными.