Tsql 使用curs查找运行总计

Tsql 使用curs查找运行总计,tsql,Tsql,我有两张桌子Accountmaster和Transactionmaster accountmaster有列 酸的 名称 住址 CLRbal 布兰奇德 Transactionmaster具有列 特朗斯诺 点 Txntype Txnamt 酸的 布兰奇德 使用游标,我希望每当发生交易类型、现金取款或现金存款时,clrbal的运行总计都打印在变量中。当运行总计为-ve时,也打印一条错误消息。我尝试了类似的操作。 在o/p中,我只能将第一笔现金存款交易金额作为运行总额 create TABLE #v (

我有两张桌子Accountmaster和Transactionmaster

accountmaster有列

酸的 名称 住址 CLRbal 布兰奇德

Transactionmaster具有列

特朗斯诺 点 Txntype Txnamt 酸的 布兰奇德


使用游标,我希望每当发生交易类型、现金取款或现金存款时,clrbal的运行总计都打印在变量中。当运行总计为-ve时,也打印一条错误消息。我尝试了类似的操作。 在o/p中,我只能将第一笔现金存款交易金额作为运行总额

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;

首先,让我们收集一些示例数据。我将添加一个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\u和READ\u运行它们。我的方法是

一,。古怪的更新

执行计划利用聚集索引,执行得非常好

在我的系统上,成本约为0.013

二,。窗口聚合函数,求和结束

执行计划也很好

每种方法都会产生这种结果

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

这听起来像是家庭作业。到目前为止你试过什么?什么不起作用?向我们展示你的代码。我同意@squillman的观点,这听起来像是家庭作业,特别是因为需要使用光标。有更合适的非光标解决方案。请将其编辑到您的问题中,而不是将其作为答案发布。
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