Сравнение наборов записей

 

Если объединения используются в 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.