排序表并获得行位置Laravel雄辩

时间:2018-05-13 13:05:06

标签: php mysql laravel eloquent

我有一个表名test_results,其中包含列--id,user_id,标记,准确度。

现在我需要根据标记和准确度对它们进行排名,所以我喜欢这个 -

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

所以,在这里我可以轻松找到排名 -

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

但是如何在不获取所有recods的情况下找到排名。对于前

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

如何找到此结果的排名。

排名因素与上述相同。

1 个答案:

答案 0 :(得分:0)

您可以在原始查询中使用同一个表的LEFT JOIN,并计算在您选择的行之前排序的所有行:

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