Laravel 在单个子句中使用多个 where 和 sum

Dol*_*rma 3 php laravel laravel-5.6

在我的数据库中,我有instagram_actions_histories一个表,其中有action_type一个列,在该列中我有不同的数据,例如123

例如,我正在尝试获取此表数据的关系并对存储在列中的值求和

$userAddedPagesList = auth()->user()->instagramPages()->with([
        'history' => function ($query)  {
            $query->select(['action_type as count'])->whereActionType(1)->sum('action_type');
        }
    ]
)->get();
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这段代码不正确,因为我想获得其中history包含多个的所有内容sum

whereActionType(1)->sum('action_type')
whereActionType(2)->sum('action_type')
whereActionType(3)->sum('action_type')
Run Code Online (Sandbox Code Playgroud)

例如(伪代码):

$userAddedPagesList = auth()->user()->instagramPages()->with([
        'history' => function ($query)  {
            $query->select(['action_type as like'])->whereActionType(1)->sum('action_type');
            $query->select(['action_type as follow'])->whereActionType(2)->sum('action_type');
            $query->select(['action_type as unfollow'])->whereActionType(3)->sum('action_type');
        }
    ]
)->get();
Run Code Online (Sandbox Code Playgroud)

更新

$userAddedPagesList = auth()->user()->instagramPages()->with([
        'history' => function ($query) {
            $query->select('*')
                ->selectSub(function ($query) {
                    return $query->selectRaw('SUM(action_type)')
                        ->where('action_type', '=', '1');
                }, 'like')
                ->selectSub(function ($query) {
                    return $query->selectRaw('SUM(action_type)')
                        ->where('action_type', '=', '2');
                }, 'follow')
                ->selectSub(function ($query) {
                    return $query->selectRaw('SUM(action_type)')
                        ->where('action_type', '=', '3');
                }, 'followBack');
        }
    ]
)->get();
Run Code Online (Sandbox Code Playgroud)

错误

Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause (SQL: select *, (select SUM(action_type) where `action_type` = 1) as `like`, (select SUM(action_type) where `action_type` = 2) as `follow`, (select SUM(action_type) where `action_type` = 3) as `followBack` from `instagram_actions_histories` where `instagram_actions_histories`.`account_id` in (1, 2, 3))
Run Code Online (Sandbox Code Playgroud)

我该如何实施这个解决方案?

更新:

Instagram帐户类:

class InstagramAccount extends Model
{
    ...

    public function schedule()
    {
        return $this->hasOne(ScheduleInstagramAccounts::class, 'account_id');
    }

    public function history()
    {
        return $this->hasMany(InstagramActionsHistory::class, 'account_id');
    }
}
Run Code Online (Sandbox Code Playgroud)

InstagramActionsHistory 类:

class InstagramActionsHistory extends Model
{
    protected $guarded=['id'];

    public function page(){
        return $this->belongsTo(InstagramAccount::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

用户类别:

class User extends Authenticatable
{
    use Notifiable;

    ...

    public function instagramPages()
    {
        return $this->hasMany(InstagramAccount::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

M K*_*aid 6

另一种获得不同类型操作的条件总和的方法,您可以hasOne()在模型中定义一个关系,InstagramAccount例如

public function history_sum()
{
    return $this->hasOne(InstagramActionsHistory::class, 'account_id')
        ->select('account_id',
            DB::raw('sum(case when action_type = 1 then 0 END) as `like`'),
            DB::raw('sum(case when action_type = 2 then 0 END) as `follow`'),
            DB::raw('sum(case when action_type = 3 then 0 END) as `followBack`')
        )->groupBy('account_id');
}
Run Code Online (Sandbox Code Playgroud)

然后你可以立即加载相关数据

$userAddedPagesList = auth()->user()->instagramPages()->with('history_sum')->get();
Run Code Online (Sandbox Code Playgroud)

使用此方法将仅执行一个额外的查询,以根据您的条件获得 3 个不同的总和结果

select `account_id`,
sum(case when action_type = 1 then action_type else 0 END) as `like`, 
sum(case when action_type = 2 then action_type else 0 END) as `follow`, 
sum(case when action_type = 3 then action_type else 0 END) as `followBack` 
from `instagram_actions_histories` 
where `instagram_actions_histories`.`account_id` in (?, ?, ?) 
group by `account_id`
Run Code Online (Sandbox Code Playgroud)

虽然与其他方法(这也是一个有效的答案)相比,使用withCount将为每个操作类型添加 3 个依赖的相关子查询,这可能会导致性能开销,但生成的查询将如下所示

select `instagram_account`.*, 
(select sum(action_type) from `instagram_actions_histories` where `instagram_account`.`id` = `instagram_actions_histories`.`account_id` and `action_type` = ?) as `like`, 
(select sum(action_type) from `instagram_actions_histories` where `instagram_account`.`id` = `instagram_actions_histories`.`account_id` and `action_type` = ?) as `follow`,
(select sum(action_type) from `instagram_actions_histories` where `instagram_account`.`id` = `instagram_actions_histories`.`account_id` and `action_type` = ?) as `followBack`
from `instagram_account` 
where `instagram_account`.`user_id` = ? 
and `instagram_account`.`user_id` is not null
Run Code Online (Sandbox Code Playgroud)

要检查生成的查询,请参阅Laravel 5.3 - 如何记录页面上的所有查询?