Laravel OrderBy关系计数

Joe*_*aca 45 php mysql laravel eloquent

我正在努力获得最受欢迎的黑客马拉松,需要各自的黑客马拉松订购partipants->count().对不起,如果这有点难以理解.

我有一个具有以下格式的数据库:

hackathons
    id
    name
    ...

hackathon_user
    hackathon_id
    user_id

users
    id
    name
Run Code Online (Sandbox Code Playgroud)

Hackathon模型是:

class Hackathon extends \Eloquent {
    protected $fillable = ['name', 'begins', 'ends', 'description'];

    protected $table = 'hackathons';

    public function owner()
    {
        return $this->belongsToMany('User', 'hackathon_owner');
    }

    public function participants()
    {
        return $this->belongsToMany('User');
    }

    public function type()
    {
        return $this->belongsToMany('Type');
    }
}
Run Code Online (Sandbox Code Playgroud)

HackathonParticipant定义为:

class HackathonParticipant extends \Eloquent {

    protected $fillable = ['hackathon_id', 'user_id'];

    protected $table = 'hackathon_user';

    public function user()
    {
        return $this->belongsTo('User', 'user_id');
    }

    public function hackathon()
    {
        return $this->belongsTo('Hackathon', 'hackathon_id');
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试Hackathon::orderBy(HackathonParticipant::find($this->id)->count(), 'DESC')->take(5)->get());但是我觉得我犯了一个大错误(可能是$ this-> id),因为它根本不起作用.

我怎么会去设法得到它是基于相关hackathonParticipants数量最多最流行的这种形式的比赛?

kJa*_*esy 123

这在Laravel 5.3中适用于我,使用您的示例:

Hackathon::withCount('participants')->orderBy('participants_count', 'desc')->paginate(10); 
Run Code Online (Sandbox Code Playgroud)

这样就可以在查询中对它进行排序,并且分页效果很好.

  • 这是一个比接受的答案要好得多的答案. (9认同)
  • 仅出于信息方面的考虑,如果您的关系名称使用大写字母,例如“ maleParticipants”,则查询应类似于“ withCount('maleParticipants')-> orderBy('male_participants','desc')`。 (5认同)

use*_*496 34

您应该能够使用Collection's sortBy()count()方法轻松地完成此操作.

$hackathons = Hackathon::with('participants')->get()->sortBy(function($hackathon)
{
    return $hackathon->participants->count();
});
Run Code Online (Sandbox Code Playgroud)

  • 排序方式不会在数据库级别执行此操作...因此分页时无法正常工作!当你返回一整套时很好.. (34认同)
  • `sortBy(Closure $ callback,$ options = SORT_REGULAR,bool $ descending = false)`只需将第3个参数设置为true即可. (3认同)
  • 虽然性能很差。因为它将获取查询中每一行的计数。所有计数都应放在一个查询中,以取得快速结果。 (2认同)

tis*_*chi 19

另一种方法可以是使用withCount()方法.

Hackathon::withCount('participants')
        ->orderBy('participants_count', 'desc')
        ->paginate(50);
Run Code Online (Sandbox Code Playgroud)

参考:https://laravel.com/docs/5.5/eloquent-relationships#querying-relations


小智 13

我有类似的问题,使用sortBy()是不合适的,因为分页,正如Sabrina Gelbart在之前的解决方案中评论.所以我使用db raw,这是简化的查询:

Tag::select( 
array(
    '*',
    DB::raw('(SELECT count(*) FROM link_tag WHERE tag_id = id) as count_links')) 
)->with('links')->orderBy('count_links','desc')->paginate(5);   
Run Code Online (Sandbox Code Playgroud)

  • 我为早期版本的 Laravel 找到的最佳解决方案!(新的可以使用 withCount)不确定它是什么,但我必须这样做:`tag_id = tag.id` 而不是 `tag_id = id`...此外,你可以进一步简化它!你可以不做`select`,你可以只做`orderByRaw('(SELECT count(*) FROM link_tag WHERE tag_id = tag.id) as count_links') DESC')->paginate(5)`。对于那些想知道的人,除非您正在加载关系,否则您不需要 `->with` (2认同)

小智 6

您还可以使用连接运算符。正如 Sabrina 所说,您不能在数据库级别使用 sortby。

$hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id')
           ->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`')
           ->groupBy('hackathon.id')
           ->orderBy('count','DESC')
           ->paginate(5);
Run Code Online (Sandbox Code Playgroud)

但是这段代码从数据库中获取所有记录。所以你应该手动分页。

       $hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id')
           ->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`')
           ->groupBy('hackathon.id')
           ->orderBy('count','DESC')
           ->skip(0)->take(5)->get();
Run Code Online (Sandbox Code Playgroud)

引用自:https ://stackoverflow.com/a/26384024/2186887


Neo*_*Neo 6

我需要对多个计数求和,然后用它来设置顺序。以下查询在 Laravel 8 中对我有用。

$posts = Post::withCount('comments','likes')->orderBy(\DB::raw('comments_count + likes_count'),'DESC')->get();
Run Code Online (Sandbox Code Playgroud)