【问题标题】:CakePHP how to get the running total in an entity using a virtual field?CakePHP 如何使用虚拟字段获取实体中的运行总数?
【发布时间】:2020-08-29 11:50:30
【问题描述】:

我有一个名为存款的字段,我正在尝试创建一个名为余额的虚拟字段。在我想要的输出下面,就像链接总和。

deposit   balance   
100       100
300       400
10        410

我在实体中尝试过以下代码

public $balance = 0;
protected function _getBalance()
{
    $this->balance = $this->balance + $this->deposit;
    return $this->balance;
}

我已将所有0 平衡。

我得到如下结果

deposit   balance   
    100       0
    300       0
    10        0

我怎样才能得到欲望结果?

【问题讨论】:

    标签: cakephp cumulative-sum cakephp-4.x


    【解决方案1】:

    一个实体对其他实体一无所知,但这是它能够总结余额所必需的。

    我想到的两个解决方案是 a) 迭代所有结果并修改数据,或者 b) 如果您的 DBMS 支持它们,则使用窗口函数在 SQL 级别创建运行总计。

    如果您遍历所有结果,您可以访问前一个结果的余额并计算总和并相应地填充 balance 字段,例如在结果格式化程序中:

    $query->formatResults(function (\Cake\Collection\CollectionInterface $results) {
        $previous = null;
        return $results->map(function ($row) use (&$previous) {
            if ($previous === null) {
                $row['balance'] = $row['deposit'];
            } else {
                $row['balance'] = $previous['balance'] + $row['deposit'];
            }
            
            $previous = $row;
            
            return $row;
        });
    });
    

    在 SQL 级别的窗口函数可以让你总结以前的行:

    $query->select(function (\Cake\ORM\Query $query) {
        return [
            'deposit',
            'balance' => $query
                ->func()
                ->sum('deposit')
                ->over()
                ->order('id')
                ->rows(null)
        ];
    });
    

    这将创建一个像这样的SELECT 子句:

    SELECT
        deposit,
        (
            SUM(deposit) OVER (
                ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
            )
        ) AS balance
    

    总和是在所有先前行上计算的,包括当前行。

    需要注意的是,构建器上的窗口函数仅从 CakePHP 4.1 开始支持,在以前的版本中,您必须创建自定义表达式或传递原始 SQL:

    $query->select([
        'deposit',
        'balance' => 'SUM(deposit) OVER (
            ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        )'
    ]);
    

    另见

    【讨论】:

      猜你喜欢
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多