On a simple dataset that is a hierarchy with a finite number of levels that is small, you can do this by simply self joining.
You could use this method instead of a CTE
if your database engine does not support CTE
s or if you needed to keep the query maintenance simple.
Setup using table variable
DECLARE @table table (
id int,
name varchar(10),
[date] date,
parentid int
)
insert into @table values
(1, 'AAA', '9/7/2020', 1),
(2, 'BBB', '9/8/2020', 2),
(3, 'CCC', '9/8/2020', 3),
(4, 'DDD', '9/8/2020', 4),
(5, 'EEE', '9/8/2020', 2),
(6, 'FFF', '9/8/2020', 1),
(7, 'GGG', '9/8/2020', 5),
(8, 'HHH', '9/8/2020', 3),
(9, 'III', '9/8/2020', 4),
(10, 'JJJ', '9/8/2020', 10)
Query from the @table
with 3 levels of depth
SELECT child.id, child.name, child.[date], child.parentId
FROM @table child
LEFT OUTER JOIN @table parent on child.parentid = parent.id
ORDER BY parent.parentid, child.parentid, child.id
If your data structure has nulls to indicate that there is no parent, then this query can be more efficient again, but we have to COALESCE
the Ids:
SELECT child.id, child.name, child.[date], child.parentId
FROM @table child
LEFT OUTER JOIN @table parent on child.parentid = parent.id
order by COALESCE(parent.parentid,child.parentid,child.Id), IsNull(child.parentid,child.Id), child.id
Finally, to support each additional level of recursion, add another join, ultimately you will need n-2
joins where n
is the maximum number of levels your data will support, the following supports 4 levels:
SELECT child.id, child.name, child.[date], child.parentId
FROM @table child
LEFT OUTER JOIN @table parent on child.parentid = parent.id
LEFT OUTER JOIN @table grandparent on parent.parentid = grandparent.id
order by COALESCE(grandparent.parentId, parent.parentid,child.parentid,child.Id), COALESCE(parent.parentid,child.parentid,child.Id), IsNull(child.parentid,child.Id), child.id