Зарегистрируйтесь, чтобы продолжить обучение

ANTI JOIN (левое соединение с NULL) SQL: Join

С помощью соединений мы связываем строки одной таблицы со строками другой таблицы. Но не для каждой строки может найтись подходящая под условие соединения пара. Бывают задачи, когда нам необходимо найти именно такие строки без пары.

В этом уроке мы научимся решать такие задачи с помощью LEFT JOIN и RIGHT JOIN. Прием, который мы будем использовать, часто называют ANTI JOIN, но это именно название приема, а не инструкция SQL.

Используем ANTI JOIN

Рассмотрим пример. Пусть база данных хранит информацию о покупателях и заказах.

Таблица customers хранит информацию о покупателях:

customers

customer_id customer_name email
1 Иванов А.Б. ivanov@email.com
2 Петрова В.Г. petrova@email.com
3 Сидоров Ж.З. s_idorov@email.com

Таблица orders хранит информацию о заказах, которые делали покупатели:

orders

order_id customer_id total_price
1000 1 100.00
1001 1 500.00
1002 3 300.00

View on DB Fiddle

Допустим, нам нужно получить список всех покупателей, которые еще ни разу не сделали заказ. Такую задачу можно решить с помощью левого внешнего соединения и фильтрации.

Сначала построим просто соединение двух таблиц:

SELECT
    cus.customer_name,
    ord.order_id
FROM customers AS cus
LEFT JOIN orders AS ord ON
    cus.customer_id = ord.customer_id

Результат выполнения запроса:

customer_name order_id
Иванов А.Б. 1000
Иванов А.Б. 1001
Петрова В.Г. NULL
Сидоров Ж.З. 1002

View on DB Fiddle

Столбец order_id — это первичный ключ таблицы orders. Поэтому в результате запроса там может быть значение NULL, если у клиента нет ни одного заказа. Эту особенность мы можем использовать для фильтрации с помощью оператора WHERE:

SELECT cus.customer_name -- убрали столбец order_id, он все равно не нужен
FROM customers AS cus
LEFT JOIN orders AS ord
    ON
        cus.customer_id = ord.customer_id
WHERE ord.order_id IS NULL -- отбираем только покупателей без заказа

Результат выполнения запроса:

customer_name
Петрова В.Г.

View on DB Fiddle

После фильтрации мы получили список клиентов, которые не сделали ни одного заказа.

Сравниваем LEFT ANTI JOIN и RIGHT ANTI JOIN

Выше мы рассмотрели как реализовать ANTI JOIN с помощью LEFT JOIN. Схематично это можно представить так:

left-anti-join

На схеме видно, что в результат попали только те строки из первой (левой) таблицы, которые не удалось связать ни с одной из строк второй (правой) таблицы.

Также прием ANTI JOIN можно реализовать и с помощью RIGHT JOIN:

right-anti-join

В этом случае мы получим все те строки из второй (правой) таблицы, которые не были связаны со строками из первой (левой) таблицы.

Выводы

Цель ANTI JOIN — отобрать строки, у которых нет пары при соединении таблиц. Этот прием реализуется с помощью левого или правого внешнего соединения и фильтрации. Для фильтрации мы используем столбец, который не может принимать значение NULL, например, первичный ключ. Так мы можем однозначно отличить строки без пары.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff