【问题标题】:How to calculate cash flow using calc fields?如何使用计算字段计算现金流?
【发布时间】:2015-05-12 22:24:06
【问题描述】:

我正在编写一个简单的现金流应用程序,使用 Delphi 7、firebird 2.5 和 InterBase 组件。有问题的表是这样创建的:

create table movimentos
(
id  d_inteiro not null,
date_start d_data not null,
date_end    d_data,
value   d_valor,
user    d_inteiro,
tipo_movimento d_inteiro not null, -- Indicates if it is Debit or Credit
primary key(id),
foreign key(user) references usuarios(id),
foreign key(tipo_movimento) references tipoMovimento(id)
)

我在我的 DM 内的查询中添加了一个计算字段,并将一个 DBGrid 连接到它。它基本上要做的是显示我的余额,当条目为贷方(在数据库中指定)时使用 sum,当借方时使用 sub(duh)。

为此,我必须获取最后一个余额行的值,对新条目的值求和(或减去)并将这个新的金额放入新的插入中。

好吧,我知道如何计算同一行中的值并将其放在另一列中,但找不到任何关于获取前一行值并在下一行中使用它的信息。

实现这一点的更简单方法是什么?

编辑: 补充我的问题。我想做的是这样的事情(稍微简化一下表格):

Id   date_start   value   balance  
1    03/05/15     +200     200  
2    03/08/15     +1000   1200  
3    03/09/15     -300     900  

现在,如果我为日期 03/06/15 添加一个新条目,则必须重新计算所有行,如下所示:

Id   date_start   value   balance  
1    03/05/15     +200     200
4    03/06/15     +500     700
2    03/08/15     +1000   1700  
3    03/09/15     -300    1400 

如何创建、计算和显示这个BALANCE 列基本上是我正在寻找的。
再次感谢。

【问题讨论】:

  • 您考虑过使用 SQL 和 RUNSUM 吗?而不是借方和贷方的标志,在您的价值字段上使用 + 或 - 金额,然后它是一个简单的 RUNSUM(Value) 作为余额...
  • 您不能对计算字段执行此操作。计算字段只能访问数据的当前行,除非您想在 OnCalcFields 事件中使用单独的查询,该查询为表的每一行运行单独的 SQL 语句。您需要在 SQL 语句中执行此操作;您正在寻找计算运行总数,这里有很多与在 SQL 中这样做相关的问题。
  • 对于某些数据库服务器,可以使用“窗口函数”Look at lag function in the PostgreSQL for example.
  • @Abelisto,PostgreSQL 是一个很棒的 DBMS,我认为值得迁移到它,但这是关于即将死去的 Firebird(很抱歉这么说)。
  • @TLama Window 函数已添加到 Firebird 3(目前处于测试阶段)中。

标签: delphi delphi-7 firebird firebird2.5 cumulative-sum


【解决方案1】:

InterBase 组件不支持适用于此类客户端计算的InternalCalc 字段。虽然最好在服务器端做。

在 Firebird 中,您可以使用上下文变量来计算运行总数:

SELECT m.*,
  CAST(rdb$get_context('USER_TRANSACTION', 'BALANCE') AS d_valor) AS BALANCE,
  rdb$set_context('USER_TRANSACTION', 'BALANCE', COALESCE(CAST(rdb$get_context('USER_TRANSACTION', 'BALANCE') AS d_valor), 0) + m.value) AS DUMMY
FROM movimentos m
ORDER BY date_start

另一种解决方案是使用 FOR SELECT 在存储过程中进行所需的计算并迭代数据。

BALANCE = 0;

FOR SELECT id, data_start, value
FROM movimentos
ORDER BY date_start
INTO :ID, :DATA_START, :VALUE
DO
BEGIN
  BALANCE = BALANCE + VALUE;
  SUSPEND;
END

要应用借记卡/贷记卡,请使用IIFtipo_movimento 转换为+1/-1,如果不是:

value * IIF(tipo_movimento = ?, +1, -1)

【讨论】:

  • 因为我之前从未使用过上下文变量,所以如果可能的话,我更愿意使用过程。但是在您上面发布的示例中,据我所知,我只会得到最终的总数,而这不是我想要的。将编辑我的问题,看看我是否让自己更清楚,但感谢您的帮助。
  • 它完全符合您的要求。假设你的存储过程有ID, DATA_START, VALUE, BALANCE作为它的输出参数,那么SUSPEND命令每次都会输出一条包含计算余额的记录。
  • 终于搞定了,感谢支持。最后一个问题,当我在运行时“创建”这个余额列时,如何将它链接到我的应用程序中的 dbgrid?再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多