Click here to Skip to main content
14,828,099 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
How can I avoid use cursor to implement the following? I read that it can be done with CTE but I didn't get it working with the same result.

In the example I am using two tables, the first one is the holders table containing a list of people and the transfers table where each transfer indicates a change at a specific record of the first table.

Below you can see the code, which brings the right results:

create table #holders(Person VARCHAR(50), Kind VARCHAR(50), Pctg FLOAT)
create table #transfers(Person_FROM VARCHAR(50), Person_To VARCHAR(50), Kind VARCHAR(50), Pctg_New FLOAT, Eff_Date DATE)

insert into #holders
select 'Person One', 'Kind 1', 50 union all
select 'Person Two', 'Kind 1', 50 union all
select 'Person Three', 'Kind 1', NULL union all
select 'Person Four', 'Kind 1', NULL union all
select 'Person One', 'Kind 2', 100

insert into #transfers
select 'Person One', 'Person A', 'Kind 1', 70, '2019-12-31' union all
select 'Person Two', 'Person B', 'Kind 1', 30, '2020-01-01' union all
select 'Person A', 'Person A1', 'Kind 1', 70, '2020-01-02' union all
select 'Person A', 'Person A2', 'Kind 1', 70, '2020-01-03' union all --Should Avoided
select 'Person A2', 'Person A3', 'Kind 1', 70, '2020-01-04' union all --Should Avoided
select 'Person A1', 'Person A4', 'Kind 1', 70, '2020-01-05' 

    @Person_FROM        varchar(50),
    @Person_To          varchar(50),
    @Kind               varchar(50),
    @Pctg_New           float

declare cur cursor for select Person_FROM, Person_To, Kind, Pctg_New from #transfers order by Eff_Date
open cur
fetch next from cur into @Person_FROM, @Person_To, @Kind, @Pctg_New
while @@FETCH_STATUS = 0 begin
    update #holders set Person = @Person_To, Pctg = @Pctg_New where Person = @Person_FROM AND Kind = @Kind
    fetch next from cur into @Person_FROM, @Person_To, @Kind, @Pctg_New
close cur
deallocate cur

SELECT * FROM #holders

drop table #holders
drop table #transfers

The results should be exactly the following:

I think that the key is it is needed serialized update (order by Eff_Date) and some kind of recursive (The first line should update 3 times using this flow: "Person One" --> "Person A" --> "Person A1" --> "Person A4").

Any help is welcome! Thanks in advance

What I have tried:

I tried to solve it using CTE and cross join with no luck
Updated 24-Jan-20 4:28am
ZurdoDev 24-Jan-20 10:12am
If you still need to loop but don't want to use cursor you could always use a while loop.

1 solution

You could use a WHILE loop to redo this via a UPDATE on JOIN query.

This is a functional version of this; you may be able tweak a little more performance out of it, but it does give the same results as your cursor based variety
DECLARE @DateWork DATE = (SELECT Min(Eff_Date) FROM #transfers)
DECLARE @DateStop DATE  = (SELECT Max(Eff_Date) FROM #transfers)
WHILE (@DateWork <= @DateStop) BEGIN
	SET h.Person = t.Person_To
	,   h.Pctg   = t.Pctg_New
	FROM #holders         h
	INNER JOIN #transfers t ON h.Person = t.Person_FROM AND h.Kind = t.Kind
	WHERE T.Eff_Date = @DateWork

	SET @DateWork = DateAdd(Dd, 1, @DateWork)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900