Фильмы, которых нет ни на одной полке
Задача
Костя из закупок просит инвентаризацию: «В каталоге тысяча фильмов, но часть из них мы, кажется, никогда не завозили на диски. Найди фильмы, которых нет ни в одной копии на складе, — решим, докупать или выпиливать из каталога».
Верни film_id и название всех фильмов, у которых нет ни одной записи в инвентаре.
Схема данных
Учебная база проката dvdrental:
film(film_id, title, ...)— каталог фильмов.inventory(inventory_id, film_id, ...)— физические копии дисков; каждая строка — один диск конкретного фильма. У фильма без копий записей тут просто нет.
Решение
SELECT f.film_id, f.title
FROM film f
LEFT JOIN inventory i ON i.film_id = f.film_id
WHERE i.film_id IS NULL
ORDER BY f.title;
Разбор
Это классический анти-джойн — «найди то, чего нет в другой таблице». Прямой INNER JOIN вернул бы только фильмы, у которых копии есть, а нам нужно ровно противоположное. Приём в два шага.
Сначала LEFT JOIN: он берёт все строки левой таблицы film и подтягивает совпадения из inventory. Для фильма, у которого копий нет, совпадений не находится — и Postgres подставляет в колонки inventory значения NULL. То есть после соединения такие фильмы никуда не делись, они просто «пустые» справа.
Второй шаг — WHERE i.film_id IS NULL. Это фильтр ровно по тем строкам, где справа пусто, то есть по фильмам без единой копии. Важно писать именно IS NULL, а не = NULL: сравнение = NULL в SQL всегда даёт «неизвестно», и такой фильтр не вернёт ни строки. Почему так — в вопросе как NULL ведёт себя в SQL.
Тонкость про количество строк: LEFT JOIN иногда пугают тем, что он «размножает» левую таблицу, если справа несколько совпадений. Здесь это работает нам на руку — но нас интересуют как раз строки БЕЗ совпадений, где размножения нет по определению. Полный разбор эффекта — в вопросе может ли LEFT JOIN вернуть больше строк.
Тот же результат можно получить через WHERE NOT EXISTS (...) — этот вариант разбираем в задаче клиенты, бравшие боевики, только там условие обратное, «где совпадение есть».
Ожидаемый результат
film_id | title
--- | ---
14 | Alice Fantasia
33 | Apollo Teen
36 | Argonauts Town
38 | Ark Ridgemont
41 | Arsenic Independence
87 | Boondock Ballroom
108 | Butch Panther
128 | Catch Amistad
144 | Chinatown Gladiator
148 | Chocolate Duck
… всего строк: 42 (показаны первые 10)
Прорешай такие задачи сам
Читать разбор полезно, а настоящая прокачка — самому писать запросы и получать обратную связь. В симуляторе живая база и проверка запросов, лёгкий режим — бесплатно.
Прорешать в бесплатной песочнице