November 9, 2005 at 4:57 am
Hai Brothers,
I have table called SAMPLE
It's having 2 Columns Called OBJID BIGINT, PARENTID BIGINT
This above table having the TreeView Objects like parent and child relationship
For Example,
OBJID - 1 as Root Node
OBJID 2 and 3 are child nodes of root node.
OBJID 4,5 and 6 are childs of OBJID 2
OBJID 7 and 8 are childs of OBJID 3
Datas in the table like this
OBJID PARENTID
1 0
2 1
3 1
4 2
5 2
6 2
7 3
8 3
I will give only One Node OBJID.
I want to get the all Childs OBJIDs of the Given OBJID from the table.
The result includes all the childs, grandchilds,... etc upto tail end.
Result may be in the form of string of OBJIDS concatenated by ,(Comma).
or in any form.
One Condition:
We don't use Cursor.
I need a solution for that without using cursor.
Pls Give the Solution.
November 9, 2005 at 5:11 am
You have two options without a cursor, one for SS2000, the other for SS2005.
SQL Server 2000: You have to use a while loop (or cursor) and a temptable.
SQL Server 2005: Here you can do recursive calls with CTE's (Common Table Expressions)
So, your wanted solution is either: use a while loop and temptable - or go to SQL Server 2005 and use CTE's for true recursive functionality.
There is of course a third alternative - remodel your table(s) and att a column for the materialized path, then you won't need a cursor or loop at all. Though then the cost comes in the form of maintaining that path at all times.
/Kenneth
November 9, 2005 at 7:16 am
Try the following
CREATE FUNCTION dbo.fnGetNode (
@lNodeId Int --##PARAM @lObjId The parent node for which children will be retrieved.
) RETURNS @tblNode TABLE (
ObjId Int PRIMARY KEY ,
ParentId Int
)
AS
BEGIN
DECLARE @lNextNode Int
SET @lNextNode=0
WHILE @lNextNode IS NOT NULL
BEGIN
SELECT @lNextNode = MIN(ObjId)
FROMdbo.SAMPLE
WHEREParentId = @lNodeId
AND ObjId > @lNextNode
IF @lNextNode IS NOT NULL
BEGIN
INSERT @tblNode ( ObjId, ParentId )
SELECT ObjId, ParentId
FROMSAMPLE
WHEREObjId = @lNextNode
INSERT @tblNode ( ObjId, ParentId )
SELECT ObjId, ParentId
FROMdbo.fnGetNode(@lNextNode)
END
END
RETURN
END
You then simply call the function as follows
SELECT * from dbo.fnGetNode(0)
November 10, 2005 at 3:05 am
Thanks for your reply brother,
If the OBJIDs are in descending order from parent to child means it's OK.
But it's not in descending order means the code written by you is not working.
So Please check with that.
I am waiting for your reply.
November 10, 2005 at 6:06 am
Your example suggests that the objids are in descending order.
Why don't you use David's example and check with that yourself? After all, you know your data best.
Using a function this way is no different that using a cursor anyway...
/Kenneth
November 10, 2005 at 6:57 am
If you use a cursor then you can get locking issues because the table is held open while the cursor runs.
My looping code only locks the record that is selected while the select is going on.
November 10, 2005 at 8:31 am
David, what I ment is just that some types of functions implements a 'cursory behaviour' under the hood when used in a query. In effect what you get is a row-by-row handling - which is - a cursor.
I just mentioned it because the original poster stated the requirement 'no cursor' - though he/she hasn't explained the reason for that.
/Kenneth
November 10, 2005 at 10:28 pm
Ami,
I didn't take the time to convert this to your table or column names. If you are using INT for your ID's, it's good to 727 levels... usually more than enough for most apps. For BIGINT ID's, only half that level of nesting could be achieved.
The code is self supporting and immediately demonstrable... the temp table is only for the purpose of holding the experimental data instead of taking a chance on overwriting an existing table during the demonstration. I didn't write the code but I use different renditions of it all the time...
--Hierarchy for small tables
--Will blow up if more than 800 levels using 10 digit ID's.
--Good to about 1600 levels when using 5 didig ID's
--Good to 727 levels with 10 digit ID's with a space between each and 1 on each end.
set nocount on
create table #Area (
PageID int,
ParentPageID int,
Descrip varchar(20)
)
insert into #Area values (1,null,'County 1')
insert into #Area values (2,1,'C1 Region 1')
insert into #Area values (3,1,'C1 Region 2')
insert into #Area values (4,2,'C1 R1 Unit 1')
insert into #Area values (5,2,'C1 R1 Unit 2')
insert into #Area values (6,3,'C1 R2 Unit 1')
insert into #Area values (7,null,'County 2')
insert into #Area values (8,7,'C2 Region 1')
insert into #Area values (9,1,'C1 Region 3')
select *, 0 as Level, cast(str(pageid,5) as varchar(8000)) as H into #Temp
from #Area
where ParentPageID is null
declare @lev int
set @lev = 0
while @@rowcount > 0 begin
set @lev = @lev + 1
insert into #Temp
select G.*, @lev, T.H+str(G.pageid,5)
from #Area G join #Temp T
on G.ParentPageID = T.PageID
and T.level = @lev - 1
end
select pageid, parentPageid, LEVEL,LEFT(REPLICATE(' ',Level*2)+descrip,30),h from #temp
order by H
go
drop table #temp
drop table #Area
With a little experimentation on your part, you can qucily develop different SELECT statements to do some remarkable things with it. And, as you can see, it's very simple and short.
There are many other methods to resolve hierarchical information... one method has already been posted on this thread before this message. There are some other great methods for virtually unlimited levels of nesting.
--Jeff Moden
Change is inevitable... Change for the better is not.
November 11, 2005 at 12:02 pm
this should print the tree path :
create procedure ref_id (@id int)
as
begin
declare @ref_id int,
select @ref_id = parent_id
from _table_
where child_id = @id
while @ref_id in (select child_id from _table_)
begin
set @id = @ref_id
select @ref_id = parent_id
from _table_
where child_id = @ref_id
print @id
end
end
amen...
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply