Ранжирование позиций с использованием SQL
Попытка ранжировать позиции, но вместо того, чтобы давать (1,2,3,3,5..), когда на 3-й позиции есть ничья, он дает (1,2,3,4,5...).. Помогите пожалуйста ниже код.. спасибо.............................................................................
SELECT t.*
FROM (SELECT @curRank := IF(@prev= @cur, @curRank, @curRank + 1 ) AS classPosition,student_id, @prev:=@cur, @cur:=SUM(total_marks)
FROM (SELECT m.*
FROM marks m
WHERE classform_name = ? AND term = ? AND academic_year = ? GROUP BY student_id
ORDER BY SUM(total_marks) DESC
) n CROSS JOIN
(SELECT @curRank := 0, @prev:=NULL, @cur:=NULL ) q GROUP BY student_id
) t
WHERE student_id = ?
.............................................................................
3 ответа
Вам не нужна функция RANK. Вы всегда можете ранжировать строки, присоединив таблицу к себе, и в этом случае вы можете выбрать, как определяется порядок (и ранг).
Я смешал переменные сессии /@ и агрегация может быть немного ненадежной, но вы можете просто попробовать изменить порядок выражений выбора на student_id, @cur:=SUM(total_marks), @curRank := IF(@prev= @cur, @curRank, @curRank + 1 ) AS classPosition, @prev:=@cur
Если это не поможет, я бы предложил разделить вашу агрегацию и рейтинг. На самом деле, вы уже суммируете в подзапросе, поэтому я не совсем уверен, почему вы не просто включили сумму в результаты n
,
SELECT * FROM (
SELECT @curRank := IF(@prev= @cur, @curRank, @curRank + 1 ) AS classPosition, student_id, @prev:=@cur, @cur:=overall
FROM (SELECT m.*, SUM(total_marks) AS overall
FROM marks m
WHERE classform_name = ? AND term = ? AND academic_year = ?
GROUP BY student_id
ORDER BY overall DESC
) AS n
CROSS JOIN (SELECT @curRank := 0, @prev:=NULL, @cur:=NULL ) AS q
) AS completeRankings
WHERE student_id = ?
На самом деле, ваш исходный запрос в любом случае должен был иметь другие проблемы. n
включил бы только один случайный total_marks
значение для каждого student_id; делая внешний СУММ своего рода бессмысленным.
Редактировать - это должно позволить прогрессированию позиции "пропускать" более поздние позиции в соответствии с связями:
SELECT @curRank := @curRank + 1 AS counter, @prevRank := IF(@prev=@cur, @prevRank, @curRank) AS classPosition
... опустить counter
из окончательных результатов, вам придется расширить *
в явном виде.
Ранги - настоящая боль в MySQL.
Если вы хотите получить звание для одного студента с этими условиями, я бы порекомендовал:
SELECT 1 + COUNT(*)
FROM marks m
WHERE m.classform_name = ? AND m.term = ? AND m.academic_year = ? AND
m.total_marks >= (SELECT m2.total_marks
FROM marks m2
WHERE m2.classform_name = m.classform_name AND
m2.term = m.term
m2.academic_year = m.academic_year
m2.student_id = ?
);;