Прежде всего, я думаю, что вы без необходимости используете запрос подвыбора ( Производная таблица ), чтобы получить текущий результат. Поскольку вы не выполняете дополнительную фильтрацию результата подзапроса; вы можете покончить с подзапросом и все же получить тот же результат более эффективно:
SELECT
d.dormid,
d.student_capacity,
COUNT(d.dormid) AS num
FROM Dorm AS d
LEFT JOIN Has_amenity AS h
ON h.dormid = d.dormid
GROUP BY d.dormid, d.student_capacity
Теперь вам в основном нужна функциональность Dense_Rank()
(ранг 1 - общежитие с максимальными удобствами). Оконные функции доступны только в MySQL версии 8.0.2 и далее .
В версиях MySQL <8.0.2 </strong> мы можем использовать определяемые пользователем переменные , чтобы вычислить то же самое. Основная суть этого подхода заключается в получении набора результатов в требуемом порядке в производной таблице. В этом случае нас интересует общежитие с наивысшим рейтингом; таким образом, мы получаем набор результатов в порядке убывания num
.
Теперь мы используем две переменные сеанса для хранения предыдущих значений строк, чтобы определить текущие значения строк, в предложении Select
. В основном мы храним значения предыдущих строк rank
и num
; и if
значение num
текущей строки отличается от предыдущего, мы увеличиваем rank
.
В конце концов, снова используя этот результат в качестве производной таблицы, нам просто нужно рассмотреть только те строки, где rank = 1
(с использованием предложения Where
.)
Попробуйте следующий запрос (будет работать для всех версий MySQL):
SELECT dt2.*
FROM
(
SELECT
dt.dormid,
dt.student_capacity,
@drank := IF(@n <> dt.num, @drank + 1, @drank) AS rank,
@n := dt.num AS num
FROM
(
SELECT
d.dormid,
d.student_capacity,
COUNT(d.dormid) AS num
FROM Dorm AS d
LEFT JOIN Has_amenity AS h
ON h.dormid = d.dormid
GROUP BY d.dormid, d.student_capacity
ORDER BY num DESC
) AS dt
CROSS JOIN (SELECT @drank := 0,
@n := 0) AS user_init_vars
) AS dt2
WHERE dt2.rank = 1