Php “如何使销售报告更准确”;“可伸缩”吗;?

Php “如何使销售报告更准确”;“可伸缩”吗;?,php,sql,laravel-5,Php,Sql,Laravel 5,我构建了一个应用程序来跟踪销售情况。在我的客户视图中,我希望列一个每个客户的总销售额,但随着客户群的增长,列表的加载速度越来越慢。这就是我所做的(简化): 控制器: $customers = App\Customer::get(); 视图: 型号: public function totalSales() { $invoiceLines = InvoiceLine::whereHas('invoice', function ($query) { $query->

我构建了一个应用程序来跟踪销售情况。在我的客户视图中,我希望列一个每个客户的总销售额,但随着客户群的增长,列表的加载速度越来越慢。这就是我所做的(简化):

控制器:

$customers = App\Customer::get();
视图:

型号:

public function totalSales()
{
     $invoiceLines = InvoiceLine::whereHas('invoice', function ($query) {
        $query->where('customer_id', $this->id);
     })->get();

     $sales = $invoiceLines->reduce(function ($carry, $invoiceLine) {
        return $carry + ($invoiceLine->quantity * $invoiceLine->pricePerUnit);
     });

     return $sales ?: 0;
}
使此视图/报告更具“可伸缩性”的最佳方法是什么


我一直在考虑创建一个命令,该命令计算每个客户一夜之间的总销售额,并将结果放入客户表中,但这意味着白天的数字将不准确…

这似乎是一个非常有趣的问题

我一直在考虑创建一个计算总数的命令 一夜之间每个客户的销售额,并将结果放入客户表中

这是一个很好的选择

但这意味着白天的数字不会准确

您可以通过执行以下操作来保持数字的准确性: 通过在每次开具发票时增加customers表计数

这应该适用于总销售额

  • 确保在
    customer\u id
    列上有索引
  • 搜索使用laravel对两列执行“SQL
    SUM
    ”的方法
  • 试着用
    groupby
    在2上执行“SQL
    SUM
    。这样做将取代#2
    • 加速应用程序的一个好方法是避免在循环中调用数据库。这就是#3所建议的(本例中的循环是您视图中的
      @foreach
      ,数据库调用是
      InvoiceLine::…->get();
      中的
      totalSales()

  • 添加索引(如果缺少)并减少对DB的调用次数将产生最佳结果

    我对Laravel的了解有限,但使用原始SQL实现这一点的一种方法是:

    SELECT c.name, ts.totalSales
    FROM customer c
    INNER JOIN (
      SELECT customer_id, SUM(quantity * pricePerUnit) as totalSales
      FROM invoice
      GROUP BY customer_id
    ) ts ON c.id = ts.customer_id
    

    你可以看到你试图打印的所有数据是如何一次被提取出来的?我想你可能会想用拉威尔的雄辩的东西来写出来。

    基于上述答案,我得出了以下解决方案:

    我创建了一个事件:
    App\Events\InvoiceSaved
    ,每次“触摸”发票(创建、更新或删除)时都会发送该事件。
    App\Events\InvoiceSaved
    事件将计算客户的总销售额,并将结果添加到customers表(额外字段total\u sales).现在我可以只查询我的客户表,需要查询一个关系。加载时间从7秒下降到0.5秒

    SELECT c.name, ts.totalSales
    FROM customer c
    INNER JOIN (
      SELECT customer_id, SUM(quantity * pricePerUnit) as totalSales
      FROM invoice
      GROUP BY customer_id
    ) ts ON c.id = ts.customer_id