Вы можете использовать левое соединение с той же таблицей в необработанном запросе и подсчитать все строки, упорядоченные до выбранной вами:
$result = ModelName::hydrateRaw("
select t1.*, count(t2.id) + 1 as rank
from table_name t1
left join table_name t2
on t2.mark > t1.mark
or t2.mark = t1.mark and t2.accuracy > t1.accuracy
where t1.id = ?
group by t1.id
", [$id])->first();
Затем вы можете получить доступ к рангу просто с помощью $result->rank
.
Обратите внимание, что это не обрабатывает связи (когда t2.mark = t1.mark
и t2.accuracy = t1.accuracy
).Поэтому, если связи возможны, вы должны отсортировать их по уникальному ключу (первичный ключ должен быть в порядке).Тогда предложение ON будет
on t2.mark > t1.mark
or t2.mark = t1.mark and t2.accuracy > t1.accuracy
or t2.mark = t1.mark and t2.accuracy = t1.accuracy and t2.id > t1.id
Но вы также должны настроить свой исходный запрос на:
$results = TestResult::orderBy('mark', 'desc')
->orderBy('accuracy', 'desc')
->orderBy('id', 'desc')
->get();
Демо: http://rextester.com/WMUJ37627
Также обратите внимание, что вы можетесравните кортежи в MySQL, и ваше предложение ON также может быть
on (t2.mark, t2.accuracy, t2.id) > (t1.mark, t1.accuracy, t1.id)
Но MySQL может быть не в состоянии оптимизировать его для использования индекса.
Обновление
В версии5.4 hydrateRaw()
был переименован в fromQuery()
.