将嵌套游标转换为基于集合的方法?

时间:2016-08-25 19:44:39

标签: sql-server variables reporting-services cursor

所以我终于完成了查询的更新代码 Nested Cursor based update (我无法使更新光标工作,所以我只是将所有变量插入到另一个表中,并使用join + coalesce来纠正数字。" for update"语句仍然在游标中声明,因为取出它们会打破游标,即使我删除了所有更新语句)

但是当我尝试复制并粘贴到SSRS时,所有用于游标的变量都被认为是"未声明的"

  

变量名称' @ TranLoan'已经宣布。变量名在查询批处理或存储过程中必须是唯一的。

     

必须声明标量变量" @ TranPrin"。

     

必须声明标量变量" @ DelqPrin"。

[每次在代码中显示每个变量时,相同的变量继续执行一次,并且两个游标的所有变量都在列表中并且具有相同的错误] 事情是@TranLoan只宣布一次。附件是代码的简化版本(基本上只为每个贷款1个金额而不是3个) 如果有人能想出一套基于集合的方法,我会喜欢它,所以我可以完全放弃这些游标。

表格设置

IF OBJECT_ID('tempdb.dbo.#DQ') IS NOT NULL DROP TABLE #DQ
IF OBJECT_ID('tempdb.dbo.#DelqAmts') IS NOT NULL DROP TABLE #DelqAmts
IF OBJECT_ID('tempdb.dbo.#Tran') IS NOT NULL DROP TABLE #Tran
--IF OBJECT_ID('tempdb.dbo.#DelqAmts') IS NOT NULL DROP TABLE #DelqAmts
CREATE TABLE #DQ
([LoanNumber] int, [Amount] money, [PaidToDate] datetime);
CREATE TABLE #DelqAmts
([LoanNumber] int, [Amount] money, [PaidToDate] datetime);
INSERT INTO #DQ
([LoanNumber], [Amount], [PaidToDate])
VALUES
(56452, 739.97, '2015-09-01 00:00:00'),
(56452, 738.35, '2015-10-01 00:00:00'),
(56452, 736.72, '2015-11-01 00:00:00'),
(56452, 735.08, '2015-12-01 00:00:00'),
(56452, 733.44, '2016-01-01 00:00:00'),
(56452, 731.79, '2016-02-01 00:00:00'),
(56452, 730.13, '2016-03-01 00:00:00'),
(56452, 728.46, '2016-04-01 00:00:00'),
(56452, 726.79, '2016-05-01 00:00:00'),
(56452, 725.1, '2016-06-01 00:00:00'),
(78553, 436.43, '2016-02-01 00:00:00'),
(78553, 435.72, '2016-03-01 00:00:00'),
(78553, 435, '2016-04-01 00:00:00'),
(78553, 434.28, '2016-05-01 00:00:00'),
(78553, 433.55, '2016-06-01 00:00:00');
CREATE TABLE #Tran
([LoanNumber] int, [TranAmount] money);
INSERT INTO #Tran
(LoanNumber, TranAmount)
VALUES
(56452, 833.97),
(78553, 1653.17);

表格设置结束

declare  @Col money = 0 -- Total Collected principal
, @TranLoan varchar(10) --Loan number for current transaction
, @TranPrin money = 0 -- Tran loan collected principal
, @POPrin money = 0 -- Tran loan collected principal
, @TranCursor as CURSOR
, @DelqLoan varchar(10)
, @DelqPrin money  -- Current loan collected principal
, @DelqPTD date 
, @DelqCursor as CURSOR


set  @TranCursor = Cursor FORWARD_ONLY 
For Select LoanNumber, [TranAmount]
From #Tran

Open @TranCursor;
Fetch next from @TranCursor into @TranLoan, @TranPrin

set @Col = 0 

while (@@Fetch_status = 0) 
Begin

select @TranLoan as Loan, @TranPrin as TPrin
set  @DelqCursor = CURSOR FORWARD_ONLY 
FOR select LoanNumber,Amount ,PaidToDate 
from #DQ
    where LoanNumber = @TranLoan 
    Order by PaidToDate Asc;
--  For update OF Amount;
    Open @DelqCursor

        Fetch next from @DelqCursor into  @DelqLoan,  @DelqPrin,@DelqPTD

        while (@@Fetch_status = 0) 

        Begin
            IF @TranPrin = 0 
            SET @DelqPrin = 0 
        End

        IF @TranPrin > 0 AND @TranPrin < @DelqPrin
        BEGIN
            SET @Col = @Col + @TranPrin 
            SET @DelqPrin = @TranPrin 
        --      select @TranLoan as Loan, @TranPrin as TPrin, @DelqPrin as DPrin, @DelqPTD as PTD, @Col as Col
                SET @TranPrin = 0
        END

        IF @TranPrin >0 AND @TranPrin > @DelqPrin
        BEGIN
            SET @TranPrin = @TranPrin - @DelqPrin
            SET @Col = @Col + @DelqPrin
        END

        Insert into #DelqAmts values (@DelqLoan,  @DelqPrin, @DelqPTD)
    Fetch next from @DelqCursor into @DelqLoan,   @DelqPrin,@DelqPTD
    End

    Close @DelqCursor-- Finished with delinquent data for this loan. We close the cursor
Fetch next from @TranCursor into @TranLoan, @TranPrin
End 

Close @TranCursor
deallocate @DelqCursor
deallocate @TranCursor

select * from #delqAmts -- This is a simplification of what I need out of this code block and isn't the end result of the report

在此之后不使用变量,因此不包括其余代码。

1 个答案:

答案 0 :(得分:0)

因此,在查看了关于结束的文档以及如何进行滚动总结之后,这变得更加容易。这是最终查询(减去表格设置)

    select LoanNumber, PaidToDate, PrincipalCollected,

    SumPrin, DelqPrin, 
    case when SumPrin <= PrincipalCollected then DelqPrin 
    When PrincipalCollected between SumPrin-DelqPrin and SumPrin then PrincipalCollected- (SumPrin-DelqPrin)
        when SumPrin > PrincipalCollected  then 0 
        end  as ColPrin,
    InterestCollected, SumInt, DelqInt, 
    case when SumInt <= InterestCollected then DelqInt 
        When InterestCollected between SumInt-DelqInt and SumInt then InterestCollected- (SumInt-DelqInt)
        when SumInt > InterestCollected  then 0 
        end  as ColInt,
    ServiceFee, SumServ, DelqServFee, 
        case when SumServ <= ServiceFee then DelqServFee 
        When ServiceFee between SumServ-DelqServFee and SumServ then ServiceFee- (SumServ-DelqServFee)
        when SumServ > ServiceFee  then 0 
        end  as ColServ
        from (
SELECT tf.LoanNumber,tf.PrincipalCollected,InterestCollected, ServiceFee, 
dq.PaidToDate,  
DelqPrin, SUM(DelqPrin) OVER (Partition by dq.LoanNumber ORDER BY dq.PaidToDate) as SumPrin,  
DelqInt, SUM(DelqInt) OVER (Partition by dq.LoanNumber ORDER BY dq.PaidToDate) as SumInt, 
DelqServFee, SUM(DelqServFee) OVER (Partition by dq.LoanNumber ORDER BY dq.PaidToDate) as SumServ

FROM   #tran tf
left join #dq dq on tf.LoanNumber = dq.LoanNumber 
) as A
ORDER BY LOanNumber, PaidToDate

作为基于集合的方法更容易。只需要将滚动总和作为子查询,然后应用公式后得到我需要的数字。