Question

I have a table called "Services" which contains a ServiceID, a ParentID and a Description, where the ParentID is the ServiceID of another record. The data is setup in such a way that it forms a multiple level hierarchy of items and the "Root" items have the ParentID set to zero. How can I have a query with a new field that shows a thread of all the parents up to the root parent for each record. Of course, root items will have this field as blank. Using cars as an example, I would like to have such text inside this field for the entry 'X3' and 'Punto' respectively:

Automobiles > Germany > BMW > 4 Wheel Drive > X3

Automobiles > Italy > FIAT > Front Wheel Drive > Punto

I suspect I should have a function to which I feed the ServiceID and which does the necessary recursion to get me the string value containing the threaded descriptions. Tried Googling unary relations but could not find an example with the code for the function I need.

Thanks in advance!

UPDATE:

Here is what my table looks like:

CREATE TABLE [dbo].[Services](
[ServiceID] [int] IDENTITY(1,1) NOT NULL,
[ParentID] [int] NULL,
[ServiceDescription] [nvarchar](250) NULL)
Was it helpful?

Solution

Here is a generic example. You can copy, paste and run it and it will show you the output. If this works you should be able to modify the table and column values to get it to work for your situation.

If      Object_ID('dbo.Services') Is Not Null Drop Table [dbo].[Services];
Create  Table [dbo].[Services] (ServiceID Int Identity(1,1) NOT NULL, ParenServiceID Int NULL, ServiceDescription Nvarchar(250) NULL);

Insert  [dbo].[Services]
Select  null, 'Automobiles'
Union   All
Select  1, 'Germany'
Union   All
Select  2, 'BMW'
Union   All
Select  3, '4 Wheel Drive'
Union   All
Select  1, 'Italy'
Union   All
Select  5, 'FIAT'
Union   All
Select  4, 'X3'
Union   All
Select  6, 'Front Wheel Drive'
Union   All
Select  8, 'Punto';

With    recurCTE As
(
        Select  h.ServiceID, h2.ParenServiceID As nextParent, Convert(Varchar(max),Isnull(h2.ServiceDescription + ' > ','') + h.ServiceDescription) As Hierarchy
        From    [dbo].[Services] h
        Left    Join [dbo].[Services] h2
                On  h.ParenServiceID = h2.ServiceID
        Union   All
        Select  rc.ServiceID, h.ParenServiceID As nextParent, Convert(Varchar(max),Isnull(h.ServiceDescription + ' > ','') + rc.Hierarchy) As Hierarchy
        From    recurCTE rc
        Join    [dbo].[Services] h
                On  rc.nextParent = h.ServiceID
),      orderedResults As
(
        Select  ServiceID, Hierarchy
        From   (Select  Row_Number() Over (Partition By ServiceID Order By Len(Hierarchy) Desc) As lenPriID,
                        ServiceID,
                        Hierarchy
                From    recurCTE) As n
        Where   lenPriID = 1
)
Select  h.*, o.Hierarchy
From    orderedResults o
Join    [dbo].[Services] h
        On  o.ServiceID = h.ServiceID
Where   ServiceDescription In ('X3','Punto');

OTHER TIPS

I would use left joins to some reasonable limit (like 20) and then concatatinate the strings:

 declare @services table (ServiceID int , ParentID int,[Description] varchar(20))

 insert @services
 select 1,null,'automobiles' union
 select 2,null,'hotels' union
 select 3,1,'Germany' union
 select 4,3,'BMW' union
 select 5,3,'Audi' union
 select 6,2,'Hawaii' union
 select 7,2,'Australia'

 select  

 s.Description+'>'+s2.Description+'>'+isnull(s3.Description,'')+'>'+isnull(s4.Description,'')
 from @services s
 left join @services s2 on (s2.ParentID=s.ServiceID)
 left join @services s3 on (s3.ParentID=s2.ServiceID)
 left join @services s4 on (s4.ParentID=s3.ServiceID)
 left join @services s5 on (s5.ParentID=s4.ServiceID)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top