J'ai une table Adresse et je souhaite trier les lignes comme parent-1 => all-child-parent-1, parent-2 => all-child-parent-2 ainsi de suite ....
Table d'adresses
ID Sort Caption Parent --------------------------- 1 1 A NULL 3 2 a 1 7 3 aaa 3 2 4 B NULL 4 5 b 2 5 6 bb 4 6 7 C NULL 8 8 c 6
NULL Parent est est une racine moyenne
Sortie souhaitée
ID Caption Parent --------------------- 1 A NULL 2 B NULL 3 a 1 4 b 2 5 bb 4 6 C NULL 7 aa 3 8 c 6
4 Réponses :
Un tel tri nécessite en quelque sorte de parcourir la hiérarchie pour calculer le chemin de chaque nœud.
Vous pouvez le faire avec une requête récursive:
with cte as (
select id, caption, parent, caption addr
from mytable
where parent is null
union all
select t.id, t.caption, t.parent, c.addr + '/' + t.caption
from cte c
inner join mytable t on t.parent = c.id
)
select
id,
row_number() over(order by addr) sort,
caption,
parent
from c
order by addr
Vous pouvez créer le chemin d'accès à chaque ligne, puis l'utiliser pour le tri. La construction utilise un CTE récursif:
with cte as (
select id, caption, parent, convert(varchar(max), format(id, '0000')) as path, 1 as lev
from t
where parent is null
union all
select t.id, t.caption, t.parent, convert(varchar(max), concat(path, '->', format(t.id, '0000'))), lev + 1
from cte join
t
on cte.id = t.parent
)
select id, caption, parent
from cte
order by path;
Ici est un violon db .
Pas besoin de récursion, utilisez simplement un tri intelligent!
SELECT ID, ROW_NUMBER() over(order by Caption) as Sort, Caption, Parent FROM Address ORDER BY Caption, Parent
SQL Fiddle: http://sqlfiddle.com/#!18/bbbbe/9
Une autre option consiste à utiliser le type de données hierarcyid
Exemple
Lvl ID Parent Caption 1 1 NULL A 2 3 1 a 3 7 3 aa 1 2 NULL B 2 4 2 b 3 5 4 bb 1 6 NULL C 2 8 6 c
Retours
Declare @YourTable Table ([ID] int,[Caption] varchar(50),[Parent] int) Insert Into @YourTable Values
(1,'A',NULL)
,(2,'B',NULL)
,(3,'a',1)
,(4,'b',2)
,(5,'bb',4)
,(6,'C',NULL)
,(7,'aa',3)
,(8,'c',6)
;with cteP as (
Select ID
,Parent
,Caption
,HierID = convert(hierarchyid,concat('/',ID,'/'))
From @YourTable
Where Parent is null
Union All
Select ID = r.ID
,Parent = r.Parent
,Caption = r.Caption
,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
From @YourTable r
Join cteP p on r.Parent = p.ID)
Select Lvl = HierID.GetLevel()
,ID
,Parent
,Caption
From cteP A
Order By A.HierID