Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Навіщо оператори INTERSECT і EXCEPT і чим їх замінювали раніше?

Поруч з UNION у SQL є ще дві операції над множинами рядків:

  • INTERSECT - рядки, що є в обох результатах;
  • EXCEPT - рядки з першого результату, яких немає в другому.

У MySQL вони з'явилися у версії 8.0.31 (у PostgreSQL є давно).

-- клієнти, що купували і в 2025, і в 2026 році
SELECT user_id FROM orders WHERE YEAR(created_at) = 2025
INTERSECT
SELECT user_id FROM orders WHERE YEAR(created_at) = 2026;

-- зареєстровані, але жодного разу не купували
SELECT id FROM users
EXCEPT
SELECT user_id FROM orders;

Як і UNION, обидві за замовчуванням прибирають дублікати; INTERSECT ALL і EXCEPT ALL - зберігають.

Чим замінювали раніше:

-- INTERSECT
SELECT DISTINCT o1.user_id
FROM orders o1
WHERE YEAR(o1.created_at) = 2025
  AND EXISTS (SELECT 1 FROM orders o2 WHERE o2.user_id = o1.user_id AND YEAR(o2.created_at) = 2026);

-- EXCEPT
SELECT u.id FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);

Чим EXCEPT кращий за NOT IN: порівняння в операціях над множинами вважає NULL рівними між собою, тож немає пастки NOT IN з NULL у підзапиті.

Коли брати що:

  • INTERSECT/EXCEPT - коли порівнюються цілі рядки кількох колонок і важлива читабельність («є тут, але немає там»).
  • EXISTS/NOT EXISTS - коли потрібні колонки лише з першої таблиці, а умова зв'язку складна; часто оптимізатор виконує їх ефективніше, особливо з індексами.

Пастка з YEAR(created_at): функція над колонкою не дає використати індекс на created_at. Для великих таблиць - діапазон: created_at >= '2025-01-01' AND created_at < '2026-01-01'.

Докладніше в документації: Операції над множинами

1

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання