Привет, Я DocuDroid!
Оценка ИИ поиска
Спасибо за оценку нашего ИИ поиска!
Мы будем признательны, если вы поделитесь своими впечатлениями, чтобы мы могли улучшить наш ИИ поиск для вас и других читателей.
GitHub

Комбинирование запросов

Андрей Аксенов

Операторы множеств UNION, INTERSECT и EXCEPT позволяют объединять результаты нескольких SELECT-запросов в один результирующий набор. Кроме того, UNION используется в рекурсивных CTE для объединения нерекурсивной и рекурсивной частей в итоговый результирующий набор.

Обзор синтаксиса

Операторы UNION, INTERSECT и EXCEPT имеют схожий синтаксис:

<query1> UNION [ALL] <query2>
<query1> INTERSECT [ALL] <query2>
<query1> EXCEPT [ALL] <query2>

<query1> и <query2> — это запросы, результаты которых объединяются оператором. Каждый запрос должен возвращать одинаковое количество столбцов с совместимыми типами данных. Узнайте подробнее в статье UNION, CASE, and Related Constructs документации PostgreSQL.

Операторы множеств работают следующим образом:

  • UNION — объединяет строки из <query1> и <query2>, удаляя дубликаты (аналогично DISTINCT).

  • INTERSECT — возвращает только те строки, которые присутствуют одновременно в <query1> и <query2>.

  • EXCEPT — возвращает строки из <query1>, которых нет в <query2>.

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

ПРИМЕЧАНИЕ

По умолчанию для UNION, INTERSECT и EXCEPT дублирующиеся строки удаляются, хотя для SELECT по умолчанию применяется ALL.

Предварительные требования

Для выполнения команд, описанных в следующих разделах, подключитесь к мастер-хосту Greengage DB с помощью psql, как описано в статье Подключение к Greengage DB с использованием psql. Создайте новую базу данных и подключитесь к ней:

CREATE DATABASE marketplace;
\c marketplace

Затем создайте три таблицы и заполните их данными:

CREATE TABLE warehouse1_products
(
    id       INT,
    name     VARCHAR(100),
    category VARCHAR(50)
)
    WITH (appendoptimized = true)
    DISTRIBUTED BY (id);

CREATE TABLE warehouse2_products
(
    id       INT,
    name     VARCHAR(100),
    category VARCHAR(50)
)
    WITH (appendoptimized = true)
    DISTRIBUTED BY (id);

CREATE TABLE warehouse3_products
(
    id       INT,
    name     VARCHAR(100),
    category VARCHAR(50)
)
    WITH (appendoptimized = true)
    DISTRIBUTED BY (id);
INSERT INTO warehouse1_products (id, name, category)
VALUES (1, 'Wireless mouse', 'Electronics'),
       (2, 'Bluetooth speaker', 'Electronics'),
       (3, 'Coffee maker', 'Home appliances'),
       (4, 'Desk lamp', 'Home appliances');

INSERT INTO warehouse2_products (id, name, category)
VALUES (3, 'Coffee maker', 'Home appliances'),
       (4, 'Desk lamp', 'Home appliances'),
       (5, 'Smartphone', 'Electronics');

INSERT INTO warehouse3_products (id, name, category)
VALUES (1, 'Wireless mouse', 'Electronics'),
       (2, 'Bluetooth speaker', 'Electronics'),
       (5, 'Smartphone', 'Electronics'),
       (6, 'Wireless headphones', 'Electronics');

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

UNION

Этот запрос использует оператор UNION для объединения товаров из двух таблиц в единый список, удаляя повторяющиеся строки:

SELECT id, name
FROM warehouse1_products

UNION

SELECT id, name
FROM warehouse2_products;

Результат выглядит так:

 id |       name
----+-------------------
  1 | Wireless mouse
  5 | Smartphone
  2 | Bluetooth speaker
  3 | Coffee maker
  4 | Desk lamp
(5 rows)

Этот SQL-запрос использует UNION ALL для объединения товаров из обеих таблиц в один список, включая все дубликаты:

SELECT id, name
FROM warehouse1_products

UNION ALL

SELECT id, name
FROM warehouse2_products;

Результат содержит дублирующиеся строки, например, Coffee maker и Desk lamp:

 id |       name
----+-------------------
  1 | Wireless mouse
  3 | Coffee maker
  4 | Desk lamp
  3 | Coffee maker
  4 | Desk lamp
  2 | Bluetooth speaker
  5 | Smartphone
(7 rows)

INTERSECT

Этот SQL-запрос использует INTERSECT, чтобы получить только те товары, которые присутствуют в обеих таблицах:

SELECT id, name
FROM warehouse1_products

INTERSECT

SELECT id, name
FROM warehouse2_products;

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

 id |     name
----+--------------
  3 | Coffee maker
  4 | Desk lamp
(2 rows)

EXCEPT

Этот SQL-запрос использует EXCEPT, чтобы получить товары, которые есть в warehouse1_products, но отсутствуют в warehouse2_products:

SELECT id, name
FROM warehouse1_products

EXCEPT

SELECT id, name
FROM warehouse2_products;

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

 id |       name
----+-------------------
  1 | Wireless mouse
  2 | Bluetooth speaker
(2 rows)

Сочетание операторов множеств

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

Этот запрос использует два оператора UNION для объединения товаров из трех таблиц в единый список:

SELECT id, name
FROM warehouse1_products

UNION

SELECT id, name
FROM warehouse2_products

UNION

SELECT id, name
FROM warehouse3_products;
 id |        name
----+---------------------
  3 | Coffee maker
  4 | Desk lamp
  5 | Smartphone
  6 | Wireless headphones
  2 | Bluetooth speaker
  1 | Wireless mouse
(6 rows)

Этот запрос сначала объединяет товары из warehouse1_products и warehouse2_products с помощью UNION, а затем исключает товары из warehouse3_products с помощью EXCEPT:

SELECT id, name
FROM warehouse1_products

UNION

SELECT id, name
FROM warehouse2_products

EXCEPT

SELECT id, name
FROM warehouse3_products;
 id |     name
----+--------------
  3 | Coffee maker
  4 | Desk lamp
(2 rows)

Этот SQL-запрос сначала находит общие строки в warehouse2_products и warehouse3_products с помощью INTERSECT, а затем добавляет к ним строки из warehouse1_products при помощи UNION:

SELECT id, name
FROM warehouse1_products

UNION

SELECT id, name
FROM warehouse2_products

INTERSECT

SELECT id, name
FROM warehouse3_products;
 id |       name
----+-------------------
  3 | Coffee maker
  4 | Desk lamp
  1 | Wireless mouse
  2 | Bluetooth speaker
  5 | Smartphone
(5 rows)

Обратите внимание, что INTERSECT имеет более высокий приоритет, чем UNION и EXCEPT.

Порядок вычисления

Круглые скобки определяют порядок, в котором выполняются операции над множествами. Без скобок UNION и EXCEPT обрабатываются слева направо. INTERSECT имеет более высокий приоритет, чем UNION и EXCEPT. Следующие SQL-запросы эквивалентны:

SELECT id, name
FROM warehouse1_products

UNION

SELECT id, name
FROM warehouse2_products

INTERSECT

SELECT id, name
FROM warehouse3_products;
SELECT id, name
FROM warehouse1_products

UNION

(SELECT id, name
FROM warehouse2_products

INTERSECT

SELECT id, name
FROM warehouse3_products);

Добавьте скобки, чтобы гарантировать выполнение операции UNION перед INTERSECT:

(SELECT id, name
 FROM warehouse1_products

 UNION

 SELECT id, name
 FROM warehouse2_products)

INTERSECT

SELECT id, name
FROM warehouse3_products;

Применение модификаторов к операциям над множествами

Если нужно добавить модификаторы (например, LIMIT) к отдельным запросам внутри операции объединения, заключайте такие запросы в скобки. Без скобок может возникнуть ошибка или модификатор применится ко всему объединенному результату, а не к отдельному запросу.

Этот SQL-запрос объединяет все товары из warehouse1_products и warehouse2_products с помощью UNION ALL, а затем ограничивает общий результат тремя строками:

(SELECT id, name
 FROM warehouse1_products

 UNION ALL

 SELECT id, name
 FROM warehouse2_products)
    LIMIT 3;
 id |      name
----+----------------
  1 | Wireless mouse
  3 | Coffee maker
  4 | Desk lamp
(3 rows)

Этот запрос сначала выбирает три строки из warehouse1_products, а затем добавляет все строки из warehouse2_products с помощью UNION ALL:

(SELECT id, name
 FROM warehouse1_products
 LIMIT 3)

UNION ALL

SELECT id, name
FROM warehouse2_products;
 id |       name
----+-------------------
  3 | Coffee maker
  4 | Desk lamp
  2 | Bluetooth speaker
  5 | Smartphone
  3 | Coffee maker
  4 | Desk lamp
(6 rows)