【问题标题】:Points Ranking in Laravel where points are equalLaravel中的积分排名,其中积分相等
【发布时间】:2021-04-21 00:19:17
【问题描述】:

我正在尝试解决如何正确显示积分排名以显示排行榜。

我的模态中目前有以下内容

 public function getPointrankAttribute(){
    $year = Carbon::parse(Carbon::now())->year;

    $pointrank = Points::query()
        ->select('member_id')->selectRaw('SUM(value) as TotalPoints')
        ->where('Year','=', $year)
        ->groupBy('member_id')
        ->orderByDesc('Totalpoints')
        ->get();

    return $pointrank->search(function($points){
        return $points->member_id == $this->id;
    }) + 1;

}

这很好用,但是它使用表格中的行位置来显示排名,所以第一条记录是第 1 条,第 2 条记录显示为第 2 条。

但是,当成员的总分相同时,就会出现问题,因为在此情况下,排名是基于在表格中的位置

看下面的例子

|member_id|totalpoints|
|   12    | 20        |
|    3    |  10       |
|   10    |  10       |
|    5    |   5       |

在此示例中基于我当前的解决方案

成员 12 = 1,成员 3 = 2,成员 10 = 3,成员 5 = 4

我想要的是以下

成员 12 = 1,成员 3 = 2,成员 10 = 2,成员 5 = 4

如果我们有超过 1 个成员共享该职位(如本例中的成员 3 和 10),我也可以添加“=”,那将是很棒的

提前致谢

【问题讨论】:

  • 如果您需要分配排名的数据库版本,请在您的问题中从点表中添加一些示例数据
  • @MKhalidJunaid 感谢您的回复。您是否需要比我的查询创建的临时表更多的信息?我已经列出了 Member_id 和 Totalpoints,它们是表中的 2 个字段。想要我想使用排名方法而不是使用行号,如我上面的问题中所列。
  • 是的,我需要点表中的示例数据,以便我可以建议将返回用户排名的 SQL 查询

标签: php sql laravel rank leaderboard


【解决方案1】:

要为您的用户获得排名,您需要首先将排名分配给不同的总分,使用 laravel 集合助手,您可以创建单独的排名集合,而不管成员 ID 是什么

$collection =collect(
[
  [
    "member_id" => 12,
    "totalpoints" => 20
  ],
  [
    "member_id" => 3,
    "totalpoints" => 10
  ],
  [
    "member_id" => 10,
    "totalpoints" => 10
  ],
  [
    "member_id" => 5,
    "totalpoints" => 5
  ],
]
);

$ranks = $collection->unique('totalpoints')
                    ->values()
                    ->mapWithKeys(function ($item, $index) {
                        return [$item['totalpoints'] => $index + 1];
                    });

确保应根据总分对原始集合进行排序。

上面将创建一个不同的点数组作为键和值作为基于总点数的排名

Array
(
    [20] => 1
    [10] => 2
    [5] => 3
)

现在您可以根据原始集合中的 id 搜索您的成员,并从排名数组中获取他们各自的排名,例如

$id = 10;
$ranks[$collection->firstWhere("member_id", $id)["totalpoints"]];

如果供应商数据库支持 RANK() 等窗口函数,还有另一种方法可以直接从数据库中获取记录的排名

我想要的是:成员 12 = 1st,成员 3 = 2nd,成员 10 = 2nd,成员 5 = 4th

为了达到你想要的结果,你只需要从上面的代码中删除->values(),这样你的结果就不会被重新索引

$ranks = $collection->unique('totalpoints')
                    ->mapWithKeys(function ($item, $index) {
                        return [$item['totalpoints'] => $index + 1];
                    });

Array
(
    [20] => 1
    [10] => 2
    [5] => 4
)

DEMO

【讨论】:

  • 感谢您的反馈,我这里唯一的问题是当我需要显示(第 4 次)时,5 分的 Member_id 5 被列为第 3(第 3)。但我将此解决方案添加到另一个项目中
  • @Brendan 我认为如果一个或多个用户的积分相同,那么排名将相同,您能否详细说明为什么没有第三名?逻辑上应该有第三名,也更新了我对你想要的输出的答案
  • @M Khalid Junaid,这是因为在我的情况下,2 个相等的第三个将跳过第四个等级。我正在尝试在 Excel 中复制排名函数。在这种情况下,它也跳过了第三名。
猜你喜欢
  • 2022-12-04
  • 1970-01-01
  • 2022-10-05
  • 2015-01-23
  • 1970-01-01
  • 2021-08-12
  • 2016-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多