Как на SQL найти отдел с самой высокой средней заработной платой?

Ответ

Для решения этой задачи нужно:

  1. Сгруппировать записи по отделам.
  2. Для каждого отдела вычислить среднюю зарплату (AVG).
  3. Отсортировать результаты по средней зарплате в убывающем порядке и взять первую запись.

Предположим, таблица employees имеет поля:

  • name (имя сотрудника)
  • department (отдел)
  • salary (зарплата)

SQL-запрос (общий синтаксис):

SELECT 
    department,
    AVG(salary) AS average_salary
FROM employees
GROUP BY department
ORDER BY average_salary DESC
LIMIT 1;

Пояснение:

  • GROUP BY department — группирует всех сотрудников по отделам.
  • AVG(salary) — вычисляет среднее арифметическое значений salary в каждой группе.
  • ORDER BY average_salary DESC — сортирует отделы по вычисленной средней зарплате от наибольшей к наименьшей.
  • LIMIT 1 (в MySQL, PostgreSQL, SQLite) / FETCH FIRST 1 ROW ONLY (в стандарте SQL) / TOP 1 (в SQL Server) — ограничивает результат одной строкой, возвращая отдел-лидер.

Вариант для SQL Server (используя TOP и WITH TIES):

SELECT TOP 1 WITH TIES
    department,
    AVG(salary) AS average_salary
FROM employees
GROUP BY department
ORDER BY average_salary DESC;

Ключевое слово WITH TIES полезно, если несколько отделов имеют одинаковую, максимальную среднюю зарплату — в этом случае будут возвращены все такие отделы.

Вариант с использованием подзапроса или CTE (если нужны все данные отдела):

WITH DepartmentAverages AS (
    SELECT 
        department,
        AVG(salary) AS avg_sal
    FROM employees
    GROUP BY department
)
SELECT * 
FROM DepartmentAverages 
WHERE avg_sal = (SELECT MAX(avg_sal) FROM DepartmentAverages);

Этот запрос также корректно обработает случай нескольких отделов с одинаковой максимальной средней зарплатой.

Ответ 18+ 🔞

Да ты посмотри, какой вопрос интересный подкинули! Надо найти отдел, где народ в среднем больше всех бабла получает. Ну, типа, где начальство не скупится, или там просто все сеньёры сидят, которые за копейки работать не будут.

Так, смотри, что нам нужно сделать, по шагам, чтобы не запутаться, как последний распиздяй:

  1. Сгруппировать по отделам. Это как в армии: всех по ротам развести. GROUP BY department — и всё, уже не толпа, а организованные банды.
  2. Для каждой такой банды посчитать среднюю зарплату. Берем все их зарплаты, складываем и делим на количество ртов. В SQL за это отвечает AVG(salary). Назовем это дело average_salary, чтобы понятно было.
  3. Найти самую жирную из этих средних зарплат. Для этого отсортируем наши группы по этой самой средней зарплате в порядке убывания — от самой большой к самой маленькой. ORDER BY average_salary DESC.
  4. Взять верхушку. И вот она, наша цель — первая строчка в этом рейтинге. LIMIT 1 (или его аналоги в других СУБД) — и готово, чемпион определён.

Вот тебе основной запрос, который на большинстве баз сработает (MySQL, PostgreSQL, SQLite):

SELECT
    department,
    AVG(salary) AS average_salary
FROM employees
GROUP BY department
ORDER BY average_salary DESC
LIMIT 1;

Но есть нюанс, ёпта! А что, если два отдела, например, «Отдел по разгребанию legacy-кода» и «Отдел по написанию отчётов», получают в среднем одинаково, и эта сумма — максимальная? Первый запрос с LIMIT 1 кинет нам только один, первый из них. А второй обидится, блядь!

Если нужно всех победителей, то вот тебе два более честных варианта:

Для SQL Server можно сделать красиво с TOP 1 и WITH TIES. Это как сказать: «Дай мне верхнюю запись, и заодно все остальные, которые к ней привязаны по значению сортировки».

SELECT TOP 1 WITH TIES
    department,
    AVG(salary) AS average_salary
FROM employees
GROUP BY department
ORDER BY average_salary DESC;

А можно по-взрослому, через CTE (общее табличное выражение). Это как сначала посчитать все средние в отдельную временную табличку, а потом из неё выдернуть те, что равны максимуму.

WITH DepartmentAverages AS (
    SELECT
        department,
        AVG(salary) AS avg_sal
    FROM employees
    GROUP BY department
)
SELECT *
FROM DepartmentAverages
WHERE avg_sal = (SELECT MAX(avg_sal) FROM DepartmentAverages);

Этот способ — вообще пушка, он и несколько отделов-победителей покажет, и логика прозрачная, как слеза ребёнка. Рекомендую.

Вот и весь расклад. Главное — не перепутай AVG с SUM, а то вместо средней зарплаты фонд оплаты труда всего отдела получишь, и удивлению твоему не будет предела.