June 28, 2006 at 12:11 am
I've written a simple recursive loop that checks for a min() value until it returns null then stops. The problem I'm having is that the server loops on the final value and won't stop.
The data is essentially four rows with Placement values of 1-4 all with ParentID = 0.
create proc ShowHierarchy
@ParentID int,
@Placement int
as
begin
set nocount on
select @Placement = min(Placement)
from ParticleCMS_Particles
where ParentID = @ParentID and Placement > @Placement
while @Placement is not null
begin
print replicate('-', @@NestLevel * 1) + cast(@Placement as varchar)
exec dbo.ShowHierarchy @ParentID, @Placement
end
end
go
exec ShowHierarchy 0,0 returns
-1
--2
---3
----4
----4
----4
... forever until I cancel the query execution
I tried using:
select top 1 @Placement = Placement
...
order by Placement
which returns
-1
--2
---3
----4
-----4
------4
-------4
--------4
...
until the server kindly stops after 32 nested levels as it is supposed to. (Even though it shouldn't ever run beyond a fifth check.)
Is there something wrong with this logic?
Can it be done with a CTE instead? (I've only made one CTE so far and though it works, I don't have my head wrapped around the concept yet.)
For those who notice that these all share the same ParentID and thus are really on the same hierarchial level, yes, I know. I actually need to be changing levels on the ParentID as it increase but the functionality is identical so ignore that minor detail for now .
June 28, 2006 at 12:07 pm
Hi..
This is an ideal candidate for a CTE. The sample CTEs in Books OnLine are very good; if you need any help getting your head around this please contact me here or on my blog.
- Ward Pond
blogs.technet.com/wardpond
June 29, 2006 at 3:35 am
The following works....I think the problem is to do with resetting your looping variable. Also nulls in results/variables are very difficult to work with!
CREATE proc ShowHierarchy
@ParentID int,
@inplacement int,
@outplacement int = null output
as
begin
set nocount on
select @outPlacement = min(Placement)
from ParticleCMS_Particles
where ParentID = @ParentID and Placement > @inPlacement
print replicate('-', @@NestLevel * 1) + cast(@outPlacement as varchar)
end
GO
CREATE proc CallShowHierarchy
@ParentID int
as
begin
set nocount on
declare @inplacement integer
declare @outplacement integer
set @outplacement = 0
set @inplacement = @outplacement
while @outPlacement is not null
begin
exec dbo.ShowHierarchy @ParentID, @inplacement, @outPlacement output
set @inplacement = @outplacement
end
end
GO
exec callshowhierarchy @parentid = 0
June 29, 2006 at 9:00 am
Just simply replace the WHILE clause by IF
Then it works:
create proc ShowHierarchy
@ParentID int,
@Placement int
as
begin
set nocount on
select @Placement = min(Placement)
from ParticleCMS_Particles
where ParentID = @ParentID and Placement > @Placement
IF @Placement is not null
begin
print replicate('-', @@NestLevel * 1) + cast(@Placement as varchar)
exec dbo.ShowHierarchy @ParentID, @Placement
end
end
go
The result of ShowHierarchy 0, 0 is:
-1
--2
---3
----4
Bye
Gabor
June 29, 2006 at 9:56 am
"Just simply replace the WHILE clause by IF"...
so bleeding obvious!...a very good lesson in standing back and keeping it simple
July 6, 2006 at 11:13 pm
Figured it out! The CTE approach eventually led me to what I was trying to do and rather simply at that. I had two problems with my initial attempts. One, I was looking for the data the wrong way and two, CTEs just weren't clicking for me. I've got it now and o is it sweet.
with
SourceRange as (
select ID, Sequence from ParticleCMS_Particles where ParentID in (7)
union all
select P.ID, P.Sequence from ParticleCMS_Particles P
inner join SourceRange S on S.ID = P.ParentID
) Select * from SourceRange
@@NestLevel won't work with CTEs and neither will something easy like a sum(1) since you can't use aggregates in a recursive. I ended up having to record the sequence in the database for other reasons to I took advantage of that to use the CTE. While I don't know what the returned sequence is, the items returned are sequential and I know the starting point so I can simply work from the starting sequence number.
Thanks, Ward. Your confirmation tat a CTE would be right for this made me take the time to finally figure them out.
July 6, 2006 at 11:32 pm
I'm glad this worked for you! FYI, you can also handle the sequencing issues within the syntax of the CTE thusly:
declare
@temp table
(ID int,
ParentID int
)
insert
@temp values (1,2)
insert @temp values (2,3)
insert @temp values (3,4)
insert @temp values (4,5)
insert @temp values (5,6)
insert @temp values (6,7)
insert @temp values (7,8)
;
with SourceRange as (
select ID, 1 AS Sequence from @temp where ParentID in (7)
union all
select P.ID, Sequence + 1 from @temp P
inner join SourceRange S on S.ID = P.ParentID
) Select * from SourceRange
I hope this helps!
- Ward Pond
blogs.technet.com/wardpond
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply