Короткий ответ
Используйте подзапрос, возвращающий идентификаторы клиентов из таблицы заказов, и оператор IN. Внешний запрос оставит клиента, если его customer_id присутствует в полученном наборе.
Как это работает подробнее
Независимый подзапрос логически формирует множество значений для сравнения. Повторяющиеся customer_id в нём не создают повторов во внешнем результате, потому что IN проверяет принадлежность, а не соединяет строки.
Коррелированный EXISTS выражает ту же задачу как проверку наличия хотя бы одной подходящей строки и часто хорошо оптимизируется как полусоединение.
Пример кода
query.sql
SELECT c.customer_id, c.email
FROM customers AS c
WHERE c.customer_id IN (
SELECT o.customer_id
FROM orders AS o
);Что использовать на практике
- Для простой принадлежности. Используйте
IN, если подзапрос короткий и читаемый. - Для наличия связи. Используйте
EXISTS, особенно если важна безопасная отрицательная проверка черезNOT EXISTS.
Подводные камни
- NOT IN и NULL. При поиске клиентов без заказов возможный
NULLв подзапросе меняет результат из-за трёхзначной логики. - JOIN без дедупликации. Обычное соединение создаст по строке на заказ, а не по строке на клиента.