Если вы работаете в SQL Server 2005+, вы можете использовать рекурсивный CTE, следя за тем, чтобы в конце вы поддерживали поле, по которому можно было упорядочить.
Попробуйте это:
declare @t table (id int, parent_id int)
insert @t
select 1,0
union all select 2,0
union all select 3,2
union all select 4,0
union all select 5,1
union all select 6,0
;
with tree as (
select t.*, convert(varbinary(max),t.id) as ordered
from @t t
where parent_id = 0
union all
select t.*, ordered + convert(varbinary(max),t.id)
from tree base
join
@t t
on t.parent_id = base.id
)
select *
from tree
order by ordered
;