В других СУБД (таких как PostgreSQL, Oracle или SQL Server) вы можете элегантно решить эту проблему с помощью оконной функции , как определено в стандарте SQL.Но MySQL не предоставляет эту функцию.
Пример для PostgreSQL :
SELECT specialty, medic, nrviz
FROM (
SELECT m.specialty
,array_to_string(ARRAY[m.nume,m.prenume], ' ') AS medic
,count(v.data_viz) AS nrviz
,row_number() OVER (PARTITON BY m.specialty
ORDER BY count(v.data_viz) DESC) AS rn
FROM visits v
JOIN medics m ON (v.medic_id = m.id_med)
WHERE year(v.data_viz) = 2005
GROUP BY m.specialty, m.nume, m.prenume
) x
WHERE rn <= 3
ORDER BY specialty, nrviz DESC, medic;
В MySQL вам придется заменить на некоторую чёрную магию, используя переменные сеанса, как вы можетенайти на этот сайт .
Редактировать:
Топ 3 медика для каждой специальности может выглядеть следующим образом для MySQL (не проверено):
SELECT x.*
FROM (SELECT @lim := 3, @spc := '') vars,
(
SELECT m.specialty
,concat(m.nume,' ',m.prenume) AS medic
,count(v.data_viz) AS nrviz
FROM visits v
JOIN medics m ON (v.medic_id = m.id_med)
WHERE year(v.data_viz) = 2005
GROUP BY 1, 2
ORDER BY 1, 3 DESC
) x
WHERE CASE WHEN @spc <> x.specialty
THEN @r := @lim
ELSE @r := @r - 1
END > 0
AND (@spc := x.specialty) IS NOT NULL
ORDER BY x.specialty, x.nrviz DESC, x.medic
Переменная для specialty
(@spc
) инициализируется пустой строкой - предполагается, что никогда не содержит пустую строку .Иначе инициализируйте к другому невозможному значению.Также предполагается, что specialty
равняется NOT NULL .
. Он просматривает упорядоченные результаты запроса и отсчитывает от @lim
(3), поэтому он принимает только первые три медика.по специальности (с наибольшим количеством посещений).Всякий раз, когда изменяется специализация, счетчик сбрасывается на @lim
.
Таким образом MySQL пробирается в процедурных элементах с переменными сеанса в SQL на основе множеств.Я называю эту черную магию, но она должна выполнить работу.