Операции над наборами строк
Реляционная модель опирается на множества, но SQL по умолчанию использует bag semantics: результат может содержать дубликаты.
UNION
Объединяет строки двух результатов:
SELECT user_id FROM orders WHERE state = 'NEW'
UNION
SELECT user_id FROM orders WHERE state = 'PAID';UNION удаляет дубликаты, UNION ALL сохраняет.
INTERSECT
Оставляет строки, присутствующие в обоих результатах:
SELECT user_id FROM orders WHERE state = 'NEW'
INTERSECT
SELECT user_id FROM orders WHERE state = 'PAID';Так находятся пользователи, у которых есть и новые, и оплаченные заказы. Поддержка INTERSECT ALL зависит от СУБД.
EXCEPT
Оставляет строки первого результата, отсутствующие во втором:
SELECT id FROM users
EXCEPT
SELECT user_id FROM orders;Это пользователи без заказов. В некоторых диалектах аналог называется MINUS.
Требования
- одинаковое число столбцов;
- совместимые типы в соответствующих позициях;
- общий
ORDER BYпосле всей операции; - имена результата обычно задает первая ветвь.
NULL и дубликаты
Для set operations строки с NULL могут считаться дубликатами/совпадающими по правилам операции, хотя обычное сравнение NULL = NULL дает UNKNOWN.
Альтернативные формы
Пересечение можно выразить EXISTS, разность — NOT EXISTS. Выбор делают по читаемости, требуемой семантике дубликатов и плану.
Связано: Объединение запросов, оператор UNION, Оператор EXISTS, Исключение дубликатов, DISTINCT.
Вопросы
Почему SQL-результат не всегда множество? По умолчанию дубликаты сохраняются.
Чем UNION отличается от UNION ALL? Первый удаляет дубликаты, второй нет.
Что делает INTERSECT? Возвращает общие строки.
Как найти строки A без соответствия в B? EXCEPT или корректный NOT EXISTS.