我正在使用Visaul Studio 2010构建Windows窗体应用程序来维护SQL Server 2008数据库中的表。该表名为CASHBOOK
,以下是更多详细信息:
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(...)
进行适当的插入,但我的问题是如何更新BALANCE
列?
答案 0 :(得分:1)
答案 1 :(得分:0)
您可以尝试使用子查询进行插入,如下所示:
INSERT INTO CASHBOOK ( DESCRIPTION, DEBIT, BALANCE )
'asdf', 2500, SELECT TOP(1) BALANCE FROM CASHBOOK + 2500
答案 2 :(得分:0)
这有点沉重,但这是一种用平衡信息更新整个表的方法。
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
答案 3 :(得分:0)
为什么需要?这应该作为报告/查看功能计算。我建议创建一个具有运行总列的视图(实现此目的的各种方法)。
或者,如果您在VB.Net中查看此内容,请在您的应用中进行计算。
答案 4 :(得分:0)
我同意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
这是一个关于递归查询的博客:Recursive CTEs
同样here's关于运行总计的冗长讨论。
答案 5 :(得分:0)
递归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. */