2016-06-29 7 views
2

私のテーブルには、以下に示すような分割記録があります。当初、プリンシパル金額は2500に割り当てられましたが、一定期間後に金額が1000ずつ増加して3500になりました。支払いテーブルを再配分する必要があります。新しい割賦金額の合計が3500支払い金額の再配分によるローン支払いテーブルの再生成

Initial records

--Initial Records 
CREATE TABLE #LOAN_REPAYMENT 
( 
TRAN_DATE DATETIME, 
INSTALLMENT_NO INT, 
PAID_AMOUNT DECIMAL(18,2) 
) 

INSERT INTO #LOAN_REPAYMENT VALUES ('1/15/2016', 11, 2000) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('2/15/2016', 11, 500) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('3/15/2016', 12, 700) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('3/28/2016', 12, 1800) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('3/28/2016', 13, 2500) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('4/15/2016', 14, 2500) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('4/15/2016', 15, 1500) 
GO 

をされますように、最初は2500年には、各割賦のために支払われた、私は結果があるべきその量を配布する必要が The result table

CREATE TABLE #LOAN_REPAYMENT_NEW 
( 
TRAN_DATE DATETIME, 
INSTALLMENT_NO INT, 
PAID_AMOUNT DECIMAL(18,2) 
) 

INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('1/15/2016', 11, 2000) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('2/15/2016', 11, 500) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('3/15/2016', 11, 700) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('3/28/2016', 11, 300) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('3/28/2016', 12, 1500) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('3/28/2016', 12, 2000) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('3/28/2016', 13, 500) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('4/15/2016', 13, 2500) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('4/15/2016', 13, 500) 
GO 
INSERT INTO #LOAN_REPAYMENT_NEW VALUES ('4/15/2016', 14, 1000) 
GO 
のような
+0

sql-generatorに使用する言語は何ですか?それはSQLのクエリかC#またはJavaですか? –

+0

私はこれをTSQL – barcanoj

答えて

1

最後のレコードの値がinstallment_noであると仮定しました(結果のスクリーンショットは13、結果コードは14と表示されます)。私はコードのコメントに答えの私の説明を含めた。

if object_id('tempdb..#loan_repayment') is not null 
    drop table #loan_repayment 

if object_id('tempdb..#loan_repayment_final') is not null 
    drop table #loan_repayment_final 

CREATE TABLE #LOAN_REPAYMENT 
( 
TRAN_DATE DATETIME, 
INSTALLMENT_NO INT, 
PAID_AMOUNT DECIMAL(18,2) 
) 

--creating the temp table for final results 
CREATE TABLE #LOAN_REPAYMENT_FINAL 
( 
TRAN_DATE DATETIME, 
INSTALLMENT_NO INT, 
PAID_AMOUNT DECIMAL(18,2), 
TRAN_RANK INT, 
ITER_VAL INT 
) 

--inserting inital sample data 
INSERT INTO #LOAN_REPAYMENT VALUES ('1/15/2016', 11, 2000) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('2/15/2016', 11, 500) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('3/15/2016', 12, 700) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('3/28/2016', 12, 1800) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('3/28/2016', 13, 2500) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('4/15/2016', 14, 2500) 
GO 
INSERT INTO #LOAN_REPAYMENT VALUES ('4/15/2016', 15, 1500) 
GO 

declare @install_no int = (select min(installment_no) from #loan_repayment) --starting installment_no 
declare @install_amt decimal(18,2) = 3500.00 --new installment amount 
declare @rec_rank int --used in while loop 
declare @i int = 0 --used to track iteration of while loop 

if object_id('tempdb..#loan_repayment_rank') is not null 
    drop table #loan_repayment_rank 

--adding additional derived columns to the initial sample data 
select lr.tran_date 
, lr.installment_no 
, lr.paid_amount 
, sum(lr.paid_amount) over (order by lr.tran_date asc, lr.installment_no asc) as unassigned_amt 
, row_number() over (order by lr.tran_date asc, lr.installment_no asc) as tran_rank 
into #loan_repayment_rank 
from #loan_repayment as lr 

while exists (select * 
       from #loan_repayment_rank as lr 
       where 1=1 
       and lr.unassigned_amt > 0) 
begin 

    --finding the highest record rank that should be included in 
    --the current installment calculation 
    set @rec_rank = coalesce((select min(lrr.tran_rank) 
           from #loan_repayment_rank as lrr 
           where 1=1 
           and unassigned_amt >= @install_amt) 
          , (select min(lrr.tran_rank) 
           from #loan_repayment_rank as lrr 
           where 1=1 
           and unassigned_amt > 0)) 

    --adding the necessary records to the fianl output 
    insert into #loan_repayment_final 
    select lrr.tran_date 
    , @install_no + @i as installment_no 
    , case when lrr.tran_rank < @rec_rank then lrr.paid_amount 
      when lrr.tran_rank = @rec_rank and lrr.paid_amount = lrr.unassigned_amt then lrr.paid_amount 
      else @install_amt - (select a.unassigned_amt from #loan_repayment_rank as a where tran_rank = @rec_rank - 1) 
     end as paid_amount 
    , lrr.tran_rank 
    , @i as iter_val 
    from #loan_repayment_rank as lrr 
    where 1=1 
    and lrr.tran_rank <= @rec_rank 
    and lrr.unassigned_amt > 0 

    --decrementing the paid amounts on the source temp table 
    --on the records effected by the current installment calculation 
    update lr 
    set lr.paid_amount = lr.paid_amount - lf.paid_amount 
    from #loan_repayment_final as lf 
    right join #loan_repayment_rank as lr on lf.tran_rank = lr.tran_rank 
    where 1=1 
    and lf.iter_val = @i 

    --updating the unassigned amount on all records 
    update lr 
    set lr.unassigned_amt = case when lr.unassigned_amt <= @install_amt then 0.00 
           else lr.unassigned_amt - @install_amt 
          end 
    from #loan_repayment_rank as lr 

    --incrementing the iteration 
    set @i += 1 

end 

--final output 
select lf.tran_date 
, lf.installment_no 
, lf.paid_amount 
from #loan_repayment_final as lf 
+0

で正確に欲しい!結果は期待通りです。ループやカーソルをCTEなどのように使わずに解決できるかどうか疑問です。 – barcanoj

+0

@barcanoj嘘つきではない、再帰的なCTEを使うことを考えましたが、これが私が思いついた解決策です。再帰的なCTEの仕事をすることができるかどうかは分かりますが、約束はありません。 – tarheel

関連する問題