我有两个表Accountmaster和Transactionmaster
accountmaster有专栏
ACID
NAME
地址
CLRbal
Branchid
Transactionmaster有列
TransNo
DOT
Txntype
Txnamt
ACID
Branchid
使用游标,我希望每当交易类型,现金提取或现金存款发生时,clrbal的运行总额就会打印在变量中。当运行总计为-ve
时,也会打印错误消息答案 0 :(得分:1)
create TABLE #v
(
acid INT ,
TXNTYPE NCHAR(3),
TXNAMT MONEY,
rt INT,
--constraint fk_acid foreign key(acid) references accountmaster(acid)
);
INSERT #v(acid, TXNTYPE, TXNAMT)
SELECT DISTINCT ACID,TXNTYPE, TXNAMT
FROM dbo.TRANSACTIONMASTER
DECLARE
@rt INT,
@ACID INT,
@TXNTYPE NCHAR(3),
@TXNAMT MONEY;
SET @rt = 0;
DECLARE c CURSOR
FOR SELECT ACID, TXNTYPE,TXNAMT FROM #v
OPEN c;
FETCH c INTO @ACID, @txntype,@txnamt;
if @TXNTYPE='cd'
BEGIN
SET @rt = @rt + @TXNAMT;
UPDATE #v SET rt = @rt WHERE acid = @ACID;
FETCH c INTO @acid,@txntype, @txnamt;
END
if @TXNTYPE='cw'
BEGIN
SET @rt = @rt - @TXNAMT;
UPDATE #v SET rt = @rt WHERE ACID = @ACID;
FETCH c INTO @acid,@txntype, @txnamt;
END
CLOSE c; DEALLOCATE c;
答案 1 :(得分:0)
首先让我们把一些样本数据放在一起。我要添加一个TXNDATE,以便我们可以排序。为简洁起见,我们将忽略NULL,MONEY数据类型等主题。
IF OBJECT_ID('tempdb..#v') IS NOT NULL DROP TABLE #v;
CREATE TABLE #v
(
TXNDATE DATE, -- something to sort by
acid INT ,
TXNTYPE NCHAR(3),
TXNAMT MONEY,
rt INT
);
--INSERT #v(acid, TXNTYPE, TXNAMT)
-- SELECT DISTINCT ACID,TXNTYPE, TXNAMT
-- FROM dbo.TRANSACTIONMASTER;
INSERT #v(TXNDATE, acid, TXNTYPE, TXNAMT)
VALUES
('20170102', 1, 'DBT', 12.01), ('20170104',1, 'CRD', 1155), ('20170112',1,'CRD',23.37),
('20170302',1, 'CRD', 124.2), ('20170303', 1, 'DBT', 819.29), ('20170402',1, 'CRD', 11.12);
我无法访问transactionmaster,因此我只会编写一些示例数据。
INSERT #v(TXNDATE, acid, TXNTYPE, TXNAMT)
VALUES
('20170102', 1, 'DBT', 12.01), ('20170104',1, 'CRD', 1155), ('20170112',1,'CRD',23.37),
('20170302',1, 'CRD', 124.2), ('20170303', 1, 'DBT', 819.29), ('20170402',1, 'CRD', 11.12);
现在我们有了
TXNDATE acid TXNTYPE TXNAMT rt
---------- ----------- ------- --------------------- -----------
2017-01-02 1 DBT 12.01 NULL
2017-01-04 1 CRD 1155.00 NULL
2017-01-12 1 CRD 23.37 NULL
2017-03-02 1 CRD 124.20 NULL
2017-03-03 1 DBT 819.29 NULL
2017-04-02 1 CRD 11.12 NULL
我假设运行总计将按日期排序。然而,首先,对于性能,我们确实需要该日期的聚簇索引。
CREATE CLUSTERED INDEX cl_v ON #v(TXNDATE);
现在我对游标知之甚少,只是说要用FORWARD_ONLY和READ_ONLY运行游标。我接近这个的方式是......
<强> 1。古怪的更新
DECLARE @runningTotal INT = 0;
UPDATE #v
SET @runningTotal = RT = (@runningTotal + CASE TXNTYPE WHEN 'DBT' THEN -TXNAMT ELSE TXNAMT END)
FROM #v WITH TABLOCKX
OPTION (MAXDOP 1);
执行计划利用聚集索引并执行得非常好。
在我的系统上,成本约为0.013 ......
<强> 2。 WINDOW Aggreage函数,(SUM OVER)
WITH CTE AS
(
SELECT *,
RT_NEW =
SUM(CASE TXNTYPE WHEN 'DBT' THEN -TXNAMT ELSE TXNAMT END) OVER (ORDER BY TXNDATE)
FROM #v
)
UPDATE CTE
SET rt=RT_NEW;
执行计划也很好。
每个都产生这个结果
TXNDATE acid TXNTYPE TXNAMT rt
---------- ----------- ------- --------------------- -----------
2017-01-02 1 DBT 12.01 -12
2017-01-04 1 CRD 1155.00 1143
2017-01-12 1 CRD 23.37 1166
2017-03-02 1 CRD 124.20 1290
2017-03-03 1 DBT 819.29 471
2017-04-02 1 CRD 11.12 482