【问题标题】:Laravel Sum transactions amount grouped by category按类别分组的 Laravel Sum 交易金额
【发布时间】:2021-01-05 02:53:24
【问题描述】:

我正在尝试汇总所有交易并将这些记录按类别与特定月份交易的总价值进行分组。

示例(当月):

Groceries => 500
Subscriptions => 100
Coffee => 0

但当前代码我只在当月发生交易时对类别进行分组,并将返回以下内容:

Groceries => 500
Subscriptions => 100

这是我的以下数据库表:

交易表:

id date category_id amount
1 2021-01-01 1 200
2 2021-01-01 1 300
3 2021-01-01 2 100
3 2020-06-06 3 100

类别表:

id display_name description
1 Groceries Food
2 Subscriptions Subscriptions
3 Coffee Coffee

我的代码选择了当月的交易,但即使没有交易也不会返回完整的类别列表。

$currentMonth = date('m');

$grouped = DB::table('categories')
  ->join('transactions', function ($join) use ($currentMonth) {
    $join->on('transactions.category_id', '=', 'categories.id')
      ->whereRaw('MONTH(date) = ?',[$currentMonth]);
    })
  ->groupBy('categories.display_name')
  ->selectRaw('sum(transactions.amount) as sum, display_name as name')
  ->pluck('sum', 'name');

【问题讨论】:

    标签: laravel


    【解决方案1】:

    WHERE 子句中的条件移动到连接的ON 子句中,并使用左连接:

    $grouped = DB::table('categories c')
        ->leftJoin('transactions t', function ($join) {
                    $join->on('t.category_id', '=', 'c.id')
                    $join->on(DB::raw('MONTH(t.date) = ?'))
                })
        ->groupBy('c.display_name')
        ->selectRaw('SUM(t.amount) AS sum, c.display_name AS name')
        ->setBindings([$currentMonth])
        ->pluck('sum', 'name');
    

    我在这里建议的原始 MySQL 查询是:

    SELECT
        c.display_name,
        SUM(t.amount) AS sum
    FROM categories c
    LEFT JOIN transactions t
        ON c.id = t.category_id AND
           MONTH(t.date) = ?
    GROUP BY
        c.display_name;
    

    上面左连接中使用的结构在这里很关键,因为它确保连接左侧的每个类别都会出现在结果集中,即使它在给定月份没有匹配的事务。

    【讨论】: