Reputation: 221
Please note that I am having 2 tables:
I want the trnamt from table salary to get updated into tbl_emi in the rec record, but the amount should not exceed the emi amount for each record,for example in this case the amount 2000 which is in the salary table should be added 1000 to the first record and another 1000 to the second record to the tbl_emi table
tbl_emi
EMI DUEDT REC Acno
1000 4/30/2014 0 123
1000 5/30/2014 0 123
1000 6/30/2014 0 123
slary
Acno Trnamt
123 2000
Upvotes: 0
Views: 69
Reputation: 166
this script should work on all cases, and should be quite efficient even on larger data sets. You can query intermediate temporary tables to see what I'm doing. Table #accumulated_amount_with_salary on each row has all the data it needs to calculate the distribution amount.
Edit: since i assumed REC is always 0 at the beginning, my query was not working correctly. I've updated the query by recalculating the EMI (substracting REC amount)
--drop table #accumulated_amount;
select a.emi-a.rec as emi, a.duedt, a.rec, a.acno, coalesce(sum(b.emi-b.rec),0) as emi_accumulated
into #accumulated_amount
from tbl_emi a
left join tbl_emi b on a.acno = b.acno and b.duedt < a.duedt
group by a.emi, a.duedt, a.rec, a.acno;
--drop table #accumulated_amount_with_salary;
select a.*, s.trnamt as salary_amt
into #accumulated_amount_with_salary
from #accumulated_amount a
inner join slary s on a.acno = s.acno;
update #accumulated_amount_with_salary
set rec = rec + case
when salary_amt < emi_accumulated then 0
when (salary_amt - emi_accumulated) < emi then salary_amt - emi_accumulated
else emi
end
update t
set rec = a.rec
from tbl_emi t
inner join #accumulated_amount_with_salary a on t.acno = a.acno and t.duedt = a.duedt;
Upvotes: 1
Reputation: 14736
Is AcNo + DUEDT unique for each row? Otherwise you need som kind of key
WITH RowRanges As (
SELECT DUEDT
,AcNo
,SUM(EMI) OVER (PARTITION BY AcNo ORDER BY DUEDT ROWS UNBOUNDED PRECEDING) - EMI AS MinValue
,SUM(EMI) OVER (PARTITION BY AcNo ORDER BY DUEDT ROWS UNBOUNDED PRECEDING) AS MaxValue
FROM tbl_emi
)
UPDATE tbl_emi
SET REC = CASE WHEN Trnamt < MaxValue THEN TrnAmt - MinValue
ELSE MaxValue - MinValue
END
FROM tbl_emi
INNER JOIN RowRanges
ON RowRanges.DUEDT = tbl_emi.DUEDT
AND RowRanges.AcNo = tbl_emi.AcNo
INNER JOIN slary
ON slary.AcNo = RowRanges.AcNo
WHERE RowRanges.MinValue < slary.Trnamt
Upvotes: 1
Reputation: 77934
You can try something like this by joining both the table on acno
and updating rec
with other table trnamt
value. In case
statement, it will check if trnamt > emi
then only half of it will be assigned else full will be assigned
UPDATE
im
SET
rec = CASE WHEN gm.trnamt > im.emi THEN (gm.trnamt - im.emi)
ELSE gm.trnamt END
FROM
tbl_emi im
JOIN
salary gm ON im.acno=gm.acno
Upvotes: 1