代码之家  ›  专栏  ›  技术社区  ›  Hardist

减少关系查询

  •  0
  • Hardist  · 技术社区  · 7 年前

    我有两个模型。 Expense Method .我想抓住 sum 全部 expenses 为每个 method type .我有四种类型:

    - bank
    - credit-card
    - wallet
    - savings
    

    每种费用都属于一种方法,每种方法都有许多费用。所以这是一对多的关系。所以一个 method_id 为每个支出存储。

    下面的查询用于获取具有类型为的方法的所有支出的总和 bank 例如:

    $type = 'bank';
    
    $expenses = auth()->user()->expenses()->with('method')->whereHas('method', function ($query) use ($type) {
            $query->where('type', $type);
        })->sum('amount');
    

    但问题是,如果我想得到每种方法类型的所有开销的总数,我将不得不运行太多的查询。我更喜欢获取所有的支出,然后过滤它们,得到每个方法类型的所有支出的总和。

    例如,以下内容不起作用:

    $expenses = auth()->user()->expenses()->with('method')->get();
    
        $bank_balance = $expenses->filter(function ($expense)
        {
            $expense->whereHas('method', function ($query) {
                $query->where('type', 'bank');
            })->get(); // with or without ->get()
        });
    

    有什么方法可以通过不使用太多的查询来获得我想要的东西吗?

    编辑:

    我没有接受所选的答案,因为它最终没有给我所需要的。在我看来,我需要能够这样做:

    {{ $bank_balance }}
    

    这意味着,有了XYZ的答案,我将无法做到这一点,因为我无法区分它们。我只得到基于方法ID的结果,但我需要能够通过方法名称来区分它们。

    DigitalFluider的答案几乎就是一个技巧,但它给了我:

    Collection {#800 ▼
      #items: array:3 [▼
        "bank" => Collection {#797 ▼
          #items: array:30 [▼
            0 => array:2 [▼
              "type" => "bank"
              "amount" => 1536
            ]
            1 => array:2 [▶]
            2 => array:2 [▶]
            3 => array:2 [▶]
            4 => array:2 [▶]
            5 => array:2 [▶]
          ]
        }
        "credit-card" => Collection {#798 ▶}
        "wallet" => Collection {#799 ▶}
      ]
    }
    

    我基本上需要这样简单的东西:

    “bank”=>“这里是所有采用‘bank’方法的支出的总额。” “信用卡”=>“所有采用‘信用卡’方式的支出的总额”

    等等……

    我觉得有点 ->groupBy('type')->each->sum('amount') 但不是完全的。它可以按类型分组,但不能为每种类型提供总和,正如您在上面的集合示例中看到的那样。

    2 回复  |  直到 7 年前
        1
  •  2
  •   xyz    7 年前

    您可以按方法ID分组,然后在select语句中对结果求和。

    以下未经测试。

    $expenses = auth()->user()
                      ->expenses()
                      ->select(DB::raw('SUM(amount) as total'), 'other_select_fields', ...)
                      ->with('method')
                      ->groupBy('method_id')
                      ->get();
    
        2
  •  1
  •   Brian Lee    7 年前

    您可以使用可用的收集方法来执行此操作:

    $expenses = auth()->user()->expenses()->with('method')->get();
    
    $groupedSums = $expenses->map(function ($expense) {
        return [
            'type' => $expense['method']['type'],
            'amount' => $expense['method']['amount']
        ];
    })->groupBy('type')->each->sum('amount');