Сравнение наборов записей
Если объединения используются в SQL для слияния полей двух источников,
то ключевые слова UNION, INTERSECT и EXCEPT сравнивают значения полей
в двух наборах и строят новый итоговый набор на основании результатов
сравнения. Каждое из перечисленных ключевых слов может использоваться
в конце синтаксически правильного запроса SQL, а за ним может следовать
второй запрос; в этом случае итоговые наборы двух запросов сравниваются
и записи либо включаются в результат, либо игнорируются.
Сравниваемые наборы данных должны содержать одинаковое количество полей,
относящихся к соответствующим типам. При этом не требуется, чтобы поля
имели одинаковые имена или принадлежали к одной таблице или источнику
данных.
- UNION. Все различающиеся записи двух наборов включаются в один набор
данных. Совпадающие записи не дублируются.
- INTERSECT. Все записи, не входящие в оба набора данных, игнорируются.
Таким образом, результат состоит только из записей, присутствующих в
обоих наборах.
- EXCEPT. Все записи, входящие в оба набора данных, игнорируются. Таким
образом, результат состоит только из тех записей набора, указанного
слева от ключевого слова EXCEPT, которые не входят в набор, указанный
справа от него.
В листингах 4.46-4.48 показаны результаты применения этих операций к
двум наборам данных. В листинге 4.46 итоговый набор формируется слиянием
фамилий авторов с названиями книг, для чего используется ключевое слово
UNION.
В листинге 4.47 продемонстрирована выборка кодов ISBN из таблицы editions.
Выборка ограничивается записями, которые упоминаются более чем в двух
поставках в таблице shi pments. Наконец, в листинге 4.48 из первого запроса
исключаются все записи, входящие во второй запрос.
Листинг 4.46. Использование секции UNION
booktown=# SELECT title FROM books
booktown-# UNION
booktown-# SELECT last_name FROM authors
booktown-# LIMIT 11;
title
2001: A Space Odyssey Alcott
Bartholomew and the Oobleck
Bianco
Bourgeois
Brautigan
Brite
Brown
Christiansen Clarke Denham
(11 rows)
Листинг 4.47. Использование секции INTERSECT
booktown=# SELECT isbn FROM editions
booktown-# INTERSECT
booktown-# SELECT isbn FROM shipments
booktown-# GROUP BY isbn
booktown-# HAVING count(id) > 2;
isbn
039480001X
0394800753
0451160916
0590445065
0694003611
(5 rows)
Листинг 4.48. Использование секции EXCEPT
booktown=# SELECT last_name, first_name
booktown-# FROM authors
booktown-# EXCEPT
booktown-# SELECT lastjiame, first_name
booktown-# FROM authors AS a (author_id)
booktown-# NATURAL INNER JOIN books
booktown-# ORDER BY first_name ASC;
last_name | first_name
Denham | Ariel
Gorey | Edward
Brite | Poppy Z.
Brautigan | Richard
(4 rows)
Команда из листинга 4.48 возвращает только те записи, которые не входят
во второй запрос. Фактически это приводит к тому, что итоговый набор состоит
из записей об авторах, у которых нет ни одной книги в таблице books. Это
связано с присутствием секции INNER JOIN, исключающей из второго запроса
всех авторов, коды которых (author_id) отсутствуют в таблице books.
Хотя присутствие этих ключевых слов в запросе SQL не позволяет использовать
в нем секцию LIMIT, этот запрет легко обходится благодаря поддержке подзапросов
в PostgreSQL. Для этого достаточно заключить в круглые скобки каждый из
запросов, участвующих в операции UNION, INTERSECT или EXCEPT, и сравнить
итоговые наборы подзапросов, как показано в листинге 4.49.
Листинг 4.49. Сравнение результатов двух
подзапросов
booktown=# (SELECT title FROM books ORDER BY title DESC
LIMIT 7)
booktown-# EXCEPT
booktown-# (SELECT title FROM books ORDER BY title ASC
LIMIT 11)
booktown-# ORDER BY title DESC;
title
The Velveteen Rabbit
The Tell-Tale Heart
The Shining
The Cat in the Hat
(4 rows)
Запрос, использованный в листинге 4.49, создает по данным таблицы books
набор, отсортированный по названию в алфавитном порядке, и выбирает из
него семь последних записей. Затем при помощи ключевого слова EXCEPT из
набора исключаются начальные 11 записей при сортировке в алфавитном порядке
по возрастаиию. Результат состоит из четырех последних записей таблицы
books, отсортированных в обратном алфавитном порядке завершающей секцией
ORDER BY. |