Learning Platform
Урок 03.04 · 14 мин
Начальный
UNIONINTERSECTEXCEPTSet operationsUnion compatibility

Раз мы согласились, что отношение — это множество, нам автоматически достаются три операции из теории множеств: объединение (∪), пересечение (∩) и разность (\). В SQL они называются UNION, INTERSECT, EXCEPT — и используются чаще, чем кажется.

Union compatibility — главное правило

Все три операции требуют, чтобы оба отношения были совместимы:

  1. Одинаковое число атрибутов.
  2. Соответствующие атрибуты — совместимых типов (text с text, integer с integer, и так далее).

Имена атрибутов могут отличаться — итоговое отношение наследует имена от левого операнда. Это часто удивляет новичков.

Несовместимые схемы — синтаксическая ошибка. PostgreSQL не «угадает» и не сделает implicit cast там, где число колонок не совпадает.

∪ — UNION (объединение)

UNION — это «всё, что есть в любом из двух отношений». В терминах множеств: A ∪ B.

UNION = A ∪ B

Все кортежи, которые встречаются хотя бы в одном из двух отношений. Дубли убраны (если не UNION ALL).

A: RU-клиенты(Аня), (Борис), (Галина)
UNION
B: DE-клиенты(Виктор), (Феликс), (Ханна)
результат6 кортежей
Аня, Борис, Галина, Виктор, Феликс, Ханна

Имена клиентов из RU ∪ имена клиентов из DE:

PostgreSQL

В этом конкретном запросе UNION даёт тот же результат, что и WHERE country IN ('RU','DE') — потому что нет пересечения по странам. Но представь, что одна выборка идёт из customers, а вторая — из совершенно другой таблицы (например, подписчиков рассылки). Тогда IN уже не сработает — а UNION объединит результаты двух запросов и устранит возможные дубликаты.

UNION vs UNION ALL — снова про bag и set

Помнишь, как SELECT без DISTINCT отличается от чистой π? То же самое здесь.

  • UNION — это множественное объединение: дубликаты удаляются. Это правильное A ∪ B с точки зрения теории.
  • UNION ALL — это мультимножественное объединение: ничего не удаляется, просто склейка результатов «как есть».

UNION стоит дороже, чем UNION ALL, потому что СУБД должна устранить дубликаты — это либо сортировка, либо построение hash-таблицы. На больших выборках разница может быть в 2–10 раз.

Сравни: UNION выдаст уникальные страны, UNION ALL — со всеми повторами

PostgreSQL

Получим 6 строк (3 + 3, с повторами). Замени UNION ALL на UNION — получишь столько строк, сколько уникальных стран среди первых трёх клиентов (скорее всего 1–2).

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

∩ — INTERSECT (пересечение)

INTERSECT — это «кортежи, которые есть в обоих отношениях». A ∩ B.

Клиенты, у которых есть и delivered, и paid заказы:

PostgreSQL

Здесь видно, как INTERSECT экономит синтаксис: альтернатива — два под-запроса с WHERE customer_id IN (...) и AND-ом между ними.

\ — EXCEPT (разность)

EXCEPT — это «кортежи из A, которых нет в B». A \ B. В Oracle и MySQL та же операция называется MINUS.

Классический сценарий: «найди клиентов, которые ни разу не покупали».

Клиенты без заказов: все клиенты минус те, кто что-то заказывал

PostgreSQL

В нашей вселенной таких клиентов мало (или нет — потому что seed-данные подобраны плотно), но в реальных базах это типичный запрос для маркетинговой воронки: «кому отправить промокод на первый заказ».

Альтернатива через NOT EXISTS или LEFT JOIN ... WHERE x IS NULL обычно эффективнее на больших объёмах, но EXCEPT гораздо читаемее и ближе к человеческому языку: «всех минус тех».

Что произойдёт с NULL

Set-операции в SQL — единственное место, где NULL = NULL ведёт себя как истинное равенство. Это исключение из общего правила трёхзначной логики, сделанное специально для UNION/INTERSECT/EXCEPT (а также для DISTINCT и GROUP BY). Если у двух строк все атрибуты равны и где-то есть NULL — для этих операций они считаются дублями.

Это удобно — иначе сравнивать строки с NULL было бы невозможно. Просто помни про этот «локальный» отказ от трёхзначной логики; в модуле 3 разберём подробно.

Проверка знанийKnowledge check
У тебя есть две выборки одинаковой схемы. В одной 100 строк, во второй 80 строк, между ними 30 общих. Сколько строк вернёт UNION? UNION ALL? INTERSECT? EXCEPT (первая минус вторая)?
ОтветAnswer
UNION = 150 (100 + 80 − 30 дублей). UNION ALL = 180 (100 + 80, без удаления дублей). INTERSECT = 30 (только общие). EXCEPT (A \\ B) = 70 (100 − 30 общих).
Свойства отношений: неупорядоченность и уникальность GROUPING SETS / CUBE / ROLLUP в DuckDB

Чек-лист

  • UNION, INTERSECT, EXCEPT — это ∪, ∩, \ из теории множеств.
  • Требование union compatibility: одинаковое число столбцов, совместимые типы.
  • UNION устраняет дубли (set-семантика). UNION ALL не устраняет (bag-семантика), и дешевле.
  • EXCEPT (в Oracle — MINUS) — компактный способ написать «всё, кроме того, что есть в B».
  • В set-операциях NULL ведёт себя как равный самому себе — это исключение из общей трёхзначной логики.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Что такое «union compatibility» в SQL?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6