排序表并获取行位置laravel elounk

8gsdolmq  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(258)

我有一个表名test\u results,其中包含列-id、user\u id、marks、accuracity。
现在我需要根据分数和准确度给他们排名,所以我喜欢这样-

$results= TestResult::orderBy('mark', 'desc')->orderBy('accuracy', 'desc')->get();

所以,在这里我可以很容易地找到排名-

foreach($results as $index => $result)
    <li>{{$result->user->name}} (Rank - {{$index + 1}}) </li>

但是我怎样才能找到排名而不获取所有记录。对于前

$result = TestResult::findOrFail($id);

我怎样才能找到这个结果的排名。
排名因子同上。

nzk0hqpo

nzk0hqpo1#

可以对原始查询中的同一个表使用左联接,并对排序在所选行之前的所有行进行计数:

$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() .

相关问题