Sql server 如何使用VB.NET在SQL Server数据库中维护运行总数?
我正在使用Visaul Studio 2010构建一个Windows窗体应用程序,以维护SQL Server 2008数据库中的表。该表名为现金簿,以下是进一步的详细信息:Sql server 如何使用VB.NET在SQL Server数据库中维护运行总数?,sql-server,vb.net,sql-server-2008,Sql Server,Vb.net,Sql Server 2008,我正在使用Visaul Studio 2010构建一个Windows窗体应用程序,以维护SQL Server 2008数据库中的表。该表名为现金簿,以下是进一步的详细信息: DATE | DESCRIPTION | DEBIT | CREDIT | BALANCE --------|----------------|---------|-----------|--------- 1/1/2011| CASH BALANCE | | |
DATE | DESCRIPTION | DEBIT | CREDIT | BALANCE
--------|----------------|---------|-----------|---------
1/1/2011| CASH BALANCE | | | 5000
1/1/2011| SALES | 2500 | | 7500
2/1/2011| PURCHASE | | 3000 | 4500
2/1/2011| RENT | | 4000 | 500
2/1/2011| SALES | 5000 | | 5500
我可以使用CASHBOOKTABLEADAPTER。插入。。。要正确插入,但我的问题是如何更新余额列?您可以尝试使用子查询进行插入,如下所示:
INSERT INTO CASHBOOK ( DESCRIPTION, DEBIT, BALANCE )
'asdf', 2500, SELECT TOP(1) BALANCE FROM CASHBOOK + 2500
这有点笨手笨脚,但这里有一种用余额信息更新整个表的方法
update
a
set
a.Balance = (
select sum(isnull(x.debit, 0.0) - isnull(x.credit, 0.0))
from cashbook x
where x.Date < a.Date
or (x.Date = a.Date and x.ID <= a.ID)
) + (
select top 1 y.Balance
from cashbook y
where y.debit is null
and y.credit is null
order by y.ID
)
from
cashbook a
现在,只有当你必须在表中有余额时,这才有用。更合适的解决方案可能是创建包含此逻辑的UDF,并仅在需要时调用该UDF来计算特定行的余额字段。这完全取决于你的使用情况
create function dbo.GetBalance(@id int) returns decimal(12, 2) as
begin
declare @result decimal(12, 2) = 0.0
select
@result = (
select sum(isnull(x.debit, 0.0) - isnull(x.credit, 0.0))
from cashbook x
where x.Date < a.Date
or (x.Date = a.Date and x.ID <= a.ID)
) + (
select top 1 y.Balance
from cashbook y
where y.debit is null
and y.credit is null
order by y.ID
)
from
cashback a
where
a.ID = @id
return @result
end
参见本文作者
你为什么要这么做?这是应该作为报告/查看功能计算的内容。我建议通过各种方法创建一个包含运行总计列的视图
或者,如果您在VB.Net中查看此信息,请在应用程序中计算。我同意Joel的观点,您应该在运行时计算此信息,而不是将运行总数存储在数据库中。以下是如何在sql server中使用递归cte计算运行总计的示例:
declare @values table (ID int identity(1,1), Value decimal(4,2))
declare @i int
insert into @values values (1.00)
insert into @values values (2.00)
insert into @values values (3.00)
insert into @values values (4.00)
insert into @values values (5.00)
insert into @values values (6.00)
select @i=min(ID) from @values
;with a as
(
select ID, Value, Value as RunningTotal
from @values
where ID=@i
union all
select b.ID, b.Value, cast(b.Value + a.RunningTotal as decimal(4,2)) as RunningTotal
from @values b
inner join a
on b.ID=a.ID+1
)
select * from a
下面是一个关于递归查询的博客:
此外,还对运行总计进行了冗长的讨论。递归CTE的一个潜在问题是最大深度限制为32767,这在生产环境中可能是禁止的 在这个解决方案中,您添加了一个id列,该列在事务序列中是有序的,然后就地更新余额列
declare @t table(id int identity(1,1) not null
, [DATE] date not null
, [DESCRIPTION] varchar(80) null
, [DEBIT] money not null default(0)
, [CREDIT] money not null default(0)
, [BALANCE] money not null default(0)
);
declare @bal money=0;
insert into @t([DATE],[DESCRIPTION],[DEBIT],[CREDIT],[BALANCE])
select '1/1/2011','CASH BALANCE',0,0,5000 UNION ALL
select '1/1/2011','SALES',2500,0,0 UNION ALL
select '2/1/2011','PURCHASE',0,3000,0 UNION ALL
select '2/1/2011','RENT',0,4000,0 UNION ALL
select '2/1/2011','SALES',5000,0,0;
set @bal=(select top 1 [BALANCE] from @t order by id); /* opening balance is stored but not computed, so we simply look it up here. */
update t
set @bal=t.[BALANCE]=(t.[DEBIT]-t.[CREDIT])+@bal
output
inserted.*
from @t t
left join @t t0 on t0.id+1=t.id; /*should order by id by default, but to be safe we force the issue here. */
整体转换为合理的情况。您需要考虑的一个问题是,如果您将按历史顺序插入行,即不只是按升序插入-假设您在2011年1月1日插入另一行,那么您将不得不更新所有后续行的余额,这可能是一个令人讨厌的HIT,我会说…您不应该!这些事情应该在最底层完成:在SQL Server数据库中。创建一个包含运行总计列的视图:您建议如何填充此列-通过三角形联接?所需的工作量与行数的平方成正比。在应用程序中计算:所以OP需要将每一行返回到他们的应用程序中,然后每次将它们相加?