Как найти самую популярную фамилию среди актеров в SQL

    При работе с базами данных часто возникает задача выявить наиболее часто встречающееся значение в столбце. В контексте таблицы actor из базы Sakila (или аналогичной) требуется определить фамилию, которая встречается у максимального числа актеров. Рассмотрим, как составить эффективный SQL-запрос для получения такого результата.

    Базовая задача: группировка и сортировка

    Исходное условие: необходимо вывести две колонки - last_name (фамилия) и count (количество актеров с такой фамилией). Результат должен содержать только одну запись - фамилию с наибольшим числом актеров.

    Простое решение с LIMIT

    Наиболее прямолинейный подход - сгруппировать записи по фамилии, подсчитать количество вхождений, отсортировать по убыванию и ограничить вывод одной строкой:

    SELECT last_name, COUNT(*) AS count
    FROM actor
    GROUP BY last_name
    ORDER BY count DESC
    LIMIT 1;

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

    Более оптимальный подход: подзапрос с агрегацией

    Чтобы гарантированно получить все фамилии с максимальным числом актеров, можно использовать вложенный запрос, который сначала находит максимальное значение count, а затем выбирает все фамилии с этим значением:

    SELECT last_name, COUNT(*) AS count
    FROM actor
    GROUP BY last_name
    HAVING COUNT(*) = (
        SELECT MAX(cnt) FROM (
            SELECT COUNT(*) AS cnt
            FROM actor
            GROUP BY last_name
        ) AS sub
    );

    Такой запрос возвращает все фамилии, у которых количество актеров равно максимальному. Это особенно полезно, когда в базе несколько фамилий-лидеров.

    Использование оконных функций (для PostgreSQL, MySQL 8+)

    В современных СУБД можно применить оконные функции для более элегантного решения:

    SELECT last_name, count
    FROM (
        SELECT last_name, COUNT(*) AS count,
               RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
        FROM actor
        GROUP BY last_name
    ) ranked
    WHERE rnk = 1;

    Этот вариант также корректно обрабатывает ситуации с несколькими фамилиями-лидерами, присваивая каждой из них ранг 1.

    Сравнение производительности

    Для больших таблиц (сотни тысяч строк) подзапрос с HAVING может выполняться дольше из-за двойного сканирования. Оконные функции часто оказываются быстрее, но требуют поддержки со стороны СУБД. В таблице actor (обычно менее 200 записей) разница незаметна, поэтому можно выбирать любой читаемый вариант.

    Практические рекомендации

    • Точность: Если важно показать все фамилии-лидеры - используйте подзапрос или оконную функцию.
    • Простота: Если достаточно одной фамилии (даже при совпадении count) - LIMIT 1 вполне уместен.
    • Индексация: Для ускорения группировки по last_name полезно создать индекс на этот столбец.

    Вывод

    Задача поиска самой популярной фамилии среди актеров решается разными способами. Базовый запрос с GROUP BY, ORDER BY и LIMIT 1 прост и эффективен, когда нужна одна запись. Для полного списка фамилий-лидеров лучше использовать подзапрос с HAVING или оконную функцию RANK(). Выбор зависит от требований к точности и версии СУБД.

    Часто задаваемые вопросы