我正在尝试获得最流行的黑客马拉松,这需要通过相应的黑客马拉松的 partipants->count()
进行排序。抱歉,如果这有点难以理解。
我有一个格式如下的数据库:
hackathons
id
name
...
hackathon_user
hackathon_id
user_id
users
id
name
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');
}
}
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');
}
}
我试过 Hackathon::orderBy(HackathonParticipant::find($this->id)->count(), 'DESC')->take(5)->get());
但我觉得我犯了一个大错误(可能是 $this->id),因为它根本不起作用。
我将如何尝试获得基于最多相关黑客马拉松参与者数量的最受欢迎的黑客马拉松?
这适用于我在 Laravel 5.3 中,使用你的例子:
Hackathon::withCount('participants')->orderBy('participants_count', 'desc')->paginate(10);
这样它在查询中被排序并且分页工作得很好。
另一种方法是使用 withCount()
方法。
Hackathon::withCount('participants')
->orderBy('participants_count', 'desc')
->paginate(50);
参考:https://laravel.com/docs/5.5/eloquent-relationships#querying-relations
编辑:如果使用 Laravel 5.2 或更高版本,请使用 kJamesy 的答案。它可能会表现得更好一些,因为它不需要将所有参与者和黑客松加载到内存中,只需将分页的黑客松和这些黑客松的参与者数量加载到内存中。
您应该能够使用 Collection
的 sortBy()
和 count()
方法相当容易地做到这一点。
$hackathons = Hackathon::with('participants')->get()->sortBy(function($hackathon)
{
return $hackathon->participants->count();
});
sortBy(Closure $callback, $options = SORT_REGULAR, bool $descending = false)
只需将第三个参数设置为 true。
我有类似的问题,并且由于分页而使用 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);
tag_id = tag.id
而不是 tag_id = id
...而且,您可以进一步简化它!您可以只执行 orderByRaw('(SELECT count(*) FROM link_tag WHERE tag_id = tag.id) as count_links') DESC')->paginate(5)
而不是执行 select
。对于那些想知道的人,除非您正在加载关系,否则您不需要 ->with
Tag::orderByLinkCount()->paginate(5)
然后在您的标签模型中使用您的 orderByRaw 语句创建 scopeOrderByLinkCount
WHERE tag_id = tag.id
而不是 WHERE tag_id = id
您也可以使用连接运算符。正如 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);
但是这段代码从数据库中获取所有记录。所以你应该手动分页。
$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();
引用自:https://stackoverflow.com/a/26384024/2186887
我需要对多个计数求和,然后用它来设置顺序。以下查询在 Laravel 8 中对我有用。
$posts = Post::withCount('comments','likes')->orderBy(\DB::raw('comments_count + likes_count'),'DESC')->get();
您可以使用以下代码
Hackathon::withCount('participants')->orderByDesc("participants_count")->paginate(15)
或者,如果您甚至想要使用单一方法的 ASC/DESC
Hackathon::withCount('participants')->orderBy("participants_count", 'asc')->paginate(15)
withCount()
maleParticipants
,则查询应类似于 thiwithCount('maleParticipants')->orderBy('male_participants', 'desc')
$this->crud->query->withCount('contactTags')->orderBy('contact_tags_count', 'desc')
。