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