Search code examples
sqlsql-serverazurehierarchy

SQL Server: How to create hierarchy combinations from a table


I have the levels of a hierarchy stacked in one table and I want to create the combinations. I tried to use recursive queries, but I could not figure it out. I am sure there must be an easy way to do this. I have different hierarchies with different number of levels, so I don't want to write a code for each and I want to have a query that handles the number of the levels. I would appreciate any help!

Here is the code to create the sample data:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [tmp].[tblSample](
    [hier] [nvarchar](255) NULL,
    [lvl] [nvarchar](255) NULL,
    [id] [int] NULL
) ON [PRIMARY]
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA00010102', N'3', 3)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA00019999', N'3', 4)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA00020107', N'3', 6)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA00029999', N'3', 7)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA11810001', N'3', 9)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA11812087', N'3', 10)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA11852299', N'3', 12)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA1185', N'2', 12)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 12)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA1181', N'2', 10)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 10)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA1181', N'2', 9)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 9)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA0002', N'2', 7)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 7)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA0002', N'2', 6)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 6)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA0001', N'2', 4)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 4)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA0001', N'2', 3)
GO
INSERT [tmp].[tblSample] ([hier], [lvl], [id]) VALUES (N'AA', N'1', 3)
GO

This is the query that I generated my desired result for this specific hierarchy:

SELECT t1.hier, t2.hier, t3.hier FROM tblSample t1 
    INNER JOIN tblSample t2 ON t1.id=t2.id AND t2.lvl=t1.lvl+1 
    INNER JOIN tblSample t3 ON t1.id=t3.id  AND t3.lvl=t1.lvl+2

sample data:

enter image description here

desired result:

enter image description here


Solution

  • This just looks like conditional aggregation to me:

    select max(case when lvl = 1 then hier end),
           max(case when lvl = 2 then hier end),
           max(case when lvl = 3 then hier end)
    from tblSample
    group by id;
    

    Alternatively, you can phrase this as joins:

    select s.hier, s2.hier, s3.hier
    from tblSample s join
         tblSample s2
         on s2.lvl = s.lvl + 1 and
            s2.id = s.id join
         tblSample s3
         on s3.lvl = s2.lvl + 1 and
            s3.id = s2.id
    where s.lvl = 1;
    

    Here is a db<>fiddle.