ChatGPT解决这个技术问题 Extra ChatGPT

Laravel OrderBy 关系计数

我正在尝试获得最流行的黑客马拉松,这需要通过相应的黑客马拉松的 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),因为它根本不起作用。

我将如何尝试获得基于最多相关黑客马拉松参与者数量的最受欢迎的黑客马拉松?


k
kJamesy

这适用于我在 Laravel 5.3 中,使用你的例子:

Hackathon::withCount('participants')->orderBy('participants_count', 'desc')->paginate(10); 

这样它在查询中被排序并且分页工作得很好。


这是一个比公认的更好的答案。
在 Laravel 5.2 中添加了方法 withCount()
非常准确和快速的答案..谢谢
仅供参考,如果您的关系名称为大写字母,例如 maleParticipants,则查询应类似于 thi withCount('maleParticipants')->orderBy('male_participants', 'desc')
谢谢你。在 Laravel Backpack 中,我可以使用 $this->crud->query->withCount('contactTags')->orderBy('contact_tags_count', 'desc')
t
tisuchi

另一种方法是使用 withCount() 方法。

Hackathon::withCount('participants')
        ->orderBy('participants_count', 'desc')
        ->paginate(50);

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


u
user1669496

编辑:如果使用 Laravel 5.2 或更高版本,请使用 kJamesy 的答案。它可能会表现得更好一些,因为它不需要将所有参与者和黑客松加载到内存中,只需将分页的黑客松和这些黑客松的参与者数量加载到内存中。

您应该能够使用 CollectionsortBy()count() 方法相当容易地做到这一点。

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

如何更改升序/降序?
sortBy(Closure $callback, $options = SORT_REGULAR, bool $descending = false) 只需将第三个参数设置为 true。
sort by 不会在数据库级别执行此操作...因此分页无法正常工作!很适合当你返回全套时..
得到错误 laravel 5.5:调用未定义的方法 Illuminate\Database\Query\Builder
虽然表现很差。因为它将获取查询中每一行的计数。所有计数都应包含在一个查询中以获得快速结果。
J
Johnyz

我有类似的问题,并且由于分页而使用 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);   

我为早期版本的 Laravel 找到的最佳解决方案! (新的可以使用 withCount)不知道它是什么,但我必须这样做: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
C
Community

您也可以使用连接运算符。正如 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


N
Neo

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

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

M
Mujahid Khan

您可以使用以下代码

Hackathon::withCount('participants')->orderByDesc("participants_count")->paginate(15)

或者,如果您甚至想要使用单一方法的 ASC/DESC

Hackathon::withCount('participants')->orderBy("participants_count", 'asc')->paginate(15)

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅