哪种方法最适合计算运行总计

时间:2014-02-02 21:28:51

标签: c# sql architecture sql-server-2012

今天晚上,我一直在思考如何打赌解决一个总计的问题。我正在使用C#with Entity Framework和SQL Server 2012开发一个可以分析我的银行交易的应用程序。

在数据库中,我创建了一个表Payment,其中包含以下属性:

PaymentDate, FromAccountId, ToAccountId, Amount

后一个属性Amount始终为正;应根据属性FromAccountIdToAccountId确定交易方向。

现在,我必须能够在任何给定时间计算运行总量。例如,通过从月末的月末减去当月的运行总计,我可以推断出特定帐户的余额。计算此运行总计将在应用程序中发挥重要作用,因此单次计算不会花费太长时间。

我已经提出了4种策略来计算这个总计:

  1. 使用存储过程,其中时间和帐户是输入参数。
  2. 计算我的应用程序中的运行总计(因为我使用的是实体框架,计算将事实上发生在数据库中)
  3. 创建表RunningTotal并为每个事务更新它。这种方法的缺点是我必须自己更新这个表,即更多业务逻辑。
  4. 与选项3类似,但随后使用基于Payment表的视图。这样,我应该处理额外的业务逻辑。
  5. 事情是,我无法决定哪种方法是最好的。你有什么想法?

1 个答案:

答案 0 :(得分:2)

在SQL Server 2012(以及Oracle和Postgres以及DB2和Teradata)中计算运行总计的最简单方法是使用累积和函数。这是一个基本的例子:

select PaymentDate, FromAccountId, ToAccountId, Amount,
       sum(Amount) over (partition by FromAccountId, ToAccountId
                         order by PaymentDate
                        ) as cumAMount
from payments;

我怀疑你想要一些稍微不同的东西,从 - >添加金额到减去 - >来自。您也可以这样做,但语法更复杂:

select PaymentDate, FromAccountId, ToAccountId, Amount,
       sum((case when FromAccountId < ToAccountId then Amount
                 else -Amount
            end
           )
          ) over
           (partition by (case when FromAccountId < ToAccountId then FromAccountId else ToAccountId end),
                         (case when FromAccountId < ToAccountId then ToAccountId else FromAccountId end)

                         order by PaymentDate
                        ) as cumAMount
from payments;

这只是在数量前面放置一个标志,具体取决于方向。然后聚合使得(FromAccountId,ToAccountId)一起使用,无论付款方向如何。