CakePHP 如何使用虚拟字段获取实体中的 运行 总数?
CakePHP how to get the running total in an entity using a virtual field?
我有一个名为 deposit 的字段,我正在尝试创建一个名为 balance 的虚拟字段。低于我的期望输出,就像链式求和。
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
我怎样才能得到想要的结果?
一个实体不知道其他实体,但为了能够总结余额,这是必需的。
我想到的两个解决方案是 a) 迭代所有结果并修改数据,或者 b) 如果您的 DBMS 支持它们,使用 window 函数创建 运行 总计 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 级别 window 函数将允许您总结前几行:
$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
其中总和是根据所有先前行计算的,包括当前行。
需要注意的是,构建器上的 window 函数仅从 CakePHP 4.1 开始受支持,在以前的版本中,您必须创建自定义表达式或传递原始 SQL:
$query->select([
'deposit',
'balance' => 'SUM(deposit) OVER (
ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)'
]);
另见
我有一个名为 deposit 的字段,我正在尝试创建一个名为 balance 的虚拟字段。低于我的期望输出,就像链式求和。
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
我怎样才能得到想要的结果?
一个实体不知道其他实体,但为了能够总结余额,这是必需的。
我想到的两个解决方案是 a) 迭代所有结果并修改数据,或者 b) 如果您的 DBMS 支持它们,使用 window 函数创建 运行 总计 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 级别 window 函数将允许您总结前几行:
$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
其中总和是根据所有先前行计算的,包括当前行。
需要注意的是,构建器上的 window 函数仅从 CakePHP 4.1 开始受支持,在以前的版本中,您必须创建自定义表达式或传递原始 SQL:
$query->select([
'deposit',
'balance' => 'SUM(deposit) OVER (
ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)'
]);
另见