Задачи на подзапросы и CTE
Подзапросы и CTE·junior

Фильмы длиннее среднего

Задача

Редактор каталога отбирает «полный метр»: «Дай фильмы, которые длиннее среднего по нашей базе. Не фиксированный порог в минутах, а именно относительно среднего — чтобы отбор сам подстраивался под каталог. Двадцати самых длинных для примера хватит».

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

Схема данных

Учебная база проката dvdrental:

  • film(film_id, title, length, ...) — каталог; length — длительность фильма в минутах.

Решение

SELECT title, length
FROM film
WHERE length > (SELECT avg(length) FROM film)
ORDER BY length DESC, title
LIMIT 20;

Разбор

«Длиннее среднего» — фраза, которая почти дословно переводится в скалярный подзапрос. Скалярный — значит возвращающий ровно одно значение (одну строку, один столбец). Подзапрос (SELECT avg(length) FROM film) считает среднюю длительность по всему каталогу и отдаёт наружу одно число. Внешний запрос сравнивает с этим числом каждый фильм: length > <среднее>.

Ключевая мысль: порог не зашит константой, а вычисляется из тех же данных. Если завтра в каталог зальют пачку короткометражек, среднее сдвинется вниз, и отбор автоматически пересоберётся — в этом сила подзапроса против «магического числа» вроде length > 115.

Почему нельзя написать просто WHERE length > avg(length)? Потому что avg — агрегат, а агрегаты в WHERE запрещены: WHERE работает на уровне отдельной строки и выполняется до того, как посчитан любой агрегат. Подзапрос обходит это ограничение — он считает среднее отдельным, самостоятельным запросом, а наружу отдаёт уже готовое число, обычную константу для сравнения.

Тонкость про NULL: если бы у части фильмов length был пустым, avg их просто проигнорировала бы (агрегаты пропускают NULL), а строки с NULL в length не прошли бы условие > — сравнение с NULL даёт «неизвестно», а не «истину». Как NULL ведёт себя в сравнениях — в вопросе как NULL ведёт себя в SQL.

ORDER BY length DESC, title ставит самые длинные наверх, а title вторым ключом разводит фильмы одинаковой длины в стабильном порядке, чтобы LIMIT 20 каждый раз отрезал одну и ту же двадцатку.

Когда порог считается не по всей таблице, а по группе — например, «длиннее всех в своём рейтинге», — подзапрос становится коррелированным, смотри задачу самые длинные фильмы в своём рейтинге.

Ожидаемый результат

title | length
--- | ---
Chicago North | 185
Control Anthem | 185
Darn Forrester | 185
Gangs Pride | 185
Home Pity | 185
Muscle Bright | 185
Pond Seattle | 185
Soldiers Evolution | 185
Sweet Brotherhood | 185
Worst Banger | 185
… всего строк: 20 (показаны первые 10)

Прорешай такие задачи сам

Читать разбор полезно, а настоящая прокачка — самому писать запросы и получать обратную связь. В симуляторе живая база и проверка запросов, лёгкий режим — бесплатно.

Прорешать в бесплатной песочнице

Смежные задачи

Вопросы по теме