Laravel Eloquent GroupBy 多对一关系

Posted

技术标签:

【中文标题】Laravel Eloquent GroupBy 多对一关系【英文标题】:Laravel Eloquent GroupBy Many To One Relationship 【发布时间】:2021-04-21 05:45:00 【问题描述】:

我有下表结构:

用户表

id name balance
1 user 1 4
2 user 2 2
3 user 3 2

special_user 表

id user_id status
1 1 1
2 2 1

订单表

id user_id provider amount date
1 1 Provider 1 10 16-01-2021
2 2 Provider 2 20 16-01-2021
3 3 Provider 1 10 16-01-2021
4 3 Provider 1 50 16-01-2021
5 1 Provider 3 15 16-01-2021
6 2 Provider 1 20 16-01-2021

我想要在刀片中的输出 html 表是(对于 16-01-2021)

Provider Users(amount) Special User (amount) Total Amount
Provider 1 1 ($60) 2 ($30) $90
Provider 2 0 ($0) 1 ($20) $20
Provider 3 0 ($0) 1 ($15) $15

Users 是他们的 ID 不在 special_user 表中的用户计数。

特殊用户是他们的 user_id 在 special_user 表中的特殊用户计数

(金额)是各类用户的订单金额之和

总金额是用户金额和特殊用户金额的总和。

以下是我尝试过的代码:

$top_providers = Orders::
        whereNotNull('provider)
        ->whereBetween('created_at', [$start_1, $end_1])
        ->groupBy('provider')
        ->selectRaw('*, count(*) as total_trans, count(transactions.user_id) as 
        all_users_count')
        ->get();

上面的代码确实根据提供者对订单进行分组,但我无法对用户类型进行分组。

请帮忙。

谢谢

【问题讨论】:

我已经格式化了表格,请帮忙!!! 我无法获得的是用户和特殊用户列 【参考方案1】:

要获得所需的结果集,您可以执行 2 个查询,一个将获取特殊用户的 id,第二个将使用这些 id 在用户之间进行分叉

在普通 SQL 中,查询看起来像

select 
  provider,
  sum(case when user_id not in(1,2) then 1 else 0 end) user_count,
  sum(case when user_id not in(1,2) then amount else 0 end) user_amount,
  sum(case when user_id in(1,2) then 1 else 0 end) special_user_count,
  sum(case when user_id in(1,2) then amount else 0 end) special_user_amount,
  sum(amount) total
from orders
group by provider

DEMO

在 laravel 中,您可以使用带有原始方法的查询构建器

$specialUserIds = SpecialUsers::where('status' , 1)->pluck('user_id')->toArray();


$orders = DB::table('orders')
            ->select('provider',
                DB::raw('sum(case when user_id not in('.$specialUserIds.') then 1 else 0 end) user_count'),
                DB::raw('sum(case when user_id not in('.$specialUserIds.') then amount else 0 end) user_amount'),
                DB::raw('sum(case when user_id in('.$specialUserIds.') then 1 else 0 end) special_user_count'),
                DB::raw('sum(case when user_id in('.$specialUserIds.') then amount else 0 end) special_user_amount'),
                DB::raw('sum(amount) total')
            )
            ->whereNotNull('provider')
            ->whereBetween('created_at', [$start_1, $end_1])
            ->groupBy('provider')
            ->get();

或者你可以通过selectRaw使用参数绑定

另外,如果用户的特殊用户表中只有一行,我建议将该状态属性移动到主用户表中,而不是创建两个具有一对一关系的表

【讨论】:

以上是关于Laravel Eloquent GroupBy 多对一关系的主要内容,如果未能解决你的问题,请参考以下文章

GroupBy() 覆盖我的选择语句 Eloquent Laravel

Laravel Eloquent GroupBy 多对一关系

Laravel 6,MYSQL - 如何使用 Laravel Querybuilder 或 Model Eloquent 将子查询与 GroupBY 左连接?

Laravel Eloquent groupBy() 并且还返回每个组的计数

Laravel Eloquent groupBy orderBy 在 MariaDB 中给出不同的结果

Laravel 按 Eloquent 关系分组