【问题标题】:How to get ranking using sub query in Laravel?如何在 Laravel 中使用子查询获得排名?
【发布时间】:2021-01-18 15:43:06
【问题描述】:

版本

Laravel:7.28.3

mysql : Ver 14.14 Distrib 5.7.29,使用 EditLine 包装器的 osx10.15 (x86_64)


表格

  1. 内容(ID)
  2. content_views (id, content_id)

我想做的事

我想通过内容视图的数量来获得内容的排名。


代码

App/Models/Content.php

  /**
   * Attribute of get rank by views
   *
   * @return Int
   */
  public function getViewsRankingAttribute()
  {
      DB::statement(DB::raw('set @c=0'));
      $result = collect(
          DB::select('select rank from
          (
              select _ranking.*, @c:=@c+1 as rank from
              (
                  select content_views.content_id, count(content_views.id) as views
                  from content_views
                  group by content_views.content_id
                  order by views desc
              ) as _ranking
          ) as ranking
          where content_id = :contentId', [
              'contentId' => $this->id
          ]))
          ->first();
      return $result ? $result->rank : '-';
  }

这实际上在 mysql 5.8 中有效,但不在 8.0 中。


错误

SQLSTATE[42000]:语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册以获取正确的语法,以便在第 1 行的 'from ( select _ranking., @c:=@c+1 as rank from ' 附近使用 (SQL: select rank from ( select _ranking.,@c:=@c+1 作为排名(从 content_views 组中选择 content_views.content_id,count(content_views.id) 作为视图,按 content_views.content_id 排序)作为 _ranking)作为排名content_id = :contentId)

【问题讨论】:

  • CTE 在 8 中的到来已经免除了对这些变量的需要。但是看到你在 PHP 中解析结果,为什么不在那里处理排名呢?
  • @Strawberry:OP 只想要特定内容的排名。要在 PHP 中执行此操作,他们需要获取整个数据集(按内容分组),然后在应用程序中进行迭代——这看起来并不理想。

标签: php mysql sql laravel window-functions


【解决方案1】:

MySQL 8.0 引入了窗口函数,这使得执行排名任务变得更加容易。另一方面,正式计划在未来版本中弃用用户变量。

是时候拥抱未来了!您可以按如下方式重写您的查询:

select *
from (
    select content_id, count(*) as views, rank() over(order by count(*) desc) rn
    from content_views
    group by content_id
) t
where content_id = :content_id

【讨论】:

    【解决方案2】:

    这确实有效!

    public function getViewsRankingAttribute()
    {
        $rank = '-';
        if ($this->views->isNotEmpty()) {
            $views = $this->views->count();
            $rank = Content::withCount('views')
                ->having('views_count', '>', $views)
                ->get()
                ->count();
            $rank++;
        }
        return $rank;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-10
      • 2019-04-01
      相关资源
      最近更新 更多