🏃🏻♀️SQL Gym Pro 10 - Разбор
Для решения задач типа «топ-N записей в каждой категории» идеально подходят оконные функции. Нам нужно проранжировать студентов внутри каждого курса.
Первым вопрос, который возникает: «Зачем нам этот топ-5?» • Если это для награждения (стипендия или оффер), то нам важно не обидеть тех, у кого равные баллы. • Если это для отчетности (просто срез данных), нам нужно фиксированное количество строк.
Используем оконки: 🔹 ROW_NUMBER(): Если у 5-го и 6-го студента по 90 баллов, один попадет в топ, а другой нет, просто по воле случая (или порядка в БД). 🔹 RANK(): При совпадении баллов даст обоим 5-е место, но следующему сразу 7-е. В общем будут пропуски в нумерации. 🔹 DENSE_RANK(): При совпадении даст обоим 5-е место, а следующему 6-е. Это самый «плотный» и честный топ для образовательных метрик.
Второй момент - это обработка краевых кейсов. • Если у студента нет оценки, он не должен попасть в топ. В ORDER BY mark DESC нуллы могут вылезти вверх (зависит от СУБД), поэтому стоит держать это в уме. • Что если один студент прошел один и тот же курс дважды? В задаче об этом ни слова, но в реальности я бы уточнил, нужно ли брать MAX(mark) перед ранжированием.
Ну и используем CTE, а также сортируем данные.
Решение: WITH RankedMarks AS ( SELECT student_name, course_name, mark, DENSE_RANK() OVER (PARTITION BY course_name ORDER BY mark DESC) as rank_place FROM marks ) SELECT student_name, course_name, mark FROM RankedMarks WHERE rank_place <= 5 ORDER BY course_name ASC, rank_place ASC;
· 21.03
Здравствуйте! Как вы считаете, в каких случаях лучше использовать СТЕ, а в каких подзапросы? И что по вашему мнению более читаемо?
ответить
коммент удалён