Den løsning, jeg foreslår her, bruger begrebet materialiseret vej. Følgende er et eksempel på materialiserede stier, der bruger dine eksempeldata. Jeg håber, det hjælper dig med at forstå materialiseret vejkoncept:
+----+--------------------------+----------+------------------+
| ID | Name | ParentID | MaterializedPath |
+----+--------------------------+----------+------------------+
| 1 | Parent 1 | 0 | 1 |
| 2 | Parent 2 | 0 | 2 |
| 4 | Parent 2 Child 1 | 2 | 2.4 |
| 6 | Parent 2 Child 1 Child 1 | 4 | 2.4.6 |
| 7 | Parent 2 Child 1 Child 2 | 4 | 2.4.7 |
| 3 | Parent 1 Child 1 | 1 | 1.3 |
| 5 | Parent 1 Child 1 Child | 3 | 1.3.5 |
+----+--------------------------+----------+------------------+
Hver node N
har en materialiseret sti, fortæller denne sti dig vejen fra rodknudepunktet til knudepunktet N
. Det kan bygges sammen med node-id'erne. For eksempel for at nå node 5
startende fra dens rodknude, besøger du node 1
, node 3
, og node 5
, så node 5
materialiseret sti er 1.3.5
Tilfældigvis kan den rækkefølge, du leder efter, opnås ved den materialiserede vej.
I det foregående eksempel er materialiserede stier konkatenerende strenge, men jeg foretrækker binær sammenkædning af en række årsager.
For at bygge de materialiserede stier har du brug for følgende rekursive CTE:
CREATE TABLE Tree
(
ID int NOT NULL CONSTRAINT PK_Tree PRIMARY KEY,
Name nvarchar(250) NOT NULL,
ParentID int NOT NULL,
)
INSERT INTO Tree(ID, Name, ParentID) VALUES
(1, 'Parent 1', 0),
(2, 'Parent 2', 0),
(3, 'Parent 1 Child 1', 1),
(4, 'Parent 2 Child 1', 2),
(5, 'Parent 1 Child 1 Child', 3),
(6, 'Parent 2 Child 1 Child 1', 4),
(7, 'Parent 2 Child 1 Child 2', 4)
GO
WITH T AS
(
SELECT
N.ID, N.Name, N.ParentID, CAST(N.ID AS varbinary(512)) AS MaterializedPath
FROM
Tree N
WHERE
N.ParentID = 0
UNION ALL
SELECT
N.ID, N.Name, N.ParentID, CAST( T.MaterializedPath + CAST(N.ID AS binary(4)) AS varbinary(512) ) AS MaterializedPath
FROM
Tree N INNER JOIN T
ON N.ParentID = T.ID
)
SELECT *
FROM T
ORDER BY T.MaterializedPath
Resultat:
+----+--------------------------+----------+----------------------------+
| ID | Name | ParentID | MaterializedPath |
+----+--------------------------+----------+----------------------------+
| 1 | Parent 1 | 0 | 0x00000001 |
| 3 | Parent 1 Child 1 | 1 | 0x0000000100000003 |
| 5 | Parent 1 Child 1 Child | 3 | 0x000000010000000300000005 |
| 2 | Parent 2 | 0 | 0x00000002 |
| 4 | Parent 2 Child 1 | 2 | 0x0000000200000004 |
| 6 | Parent 2 Child 1 Child 1 | 4 | 0x000000020000000400000006 |
| 7 | Parent 2 Child 1 Child 2 | 4 | 0x000000020000000400000007 |
+----+--------------------------+----------+----------------------------+
Ovenstående rekursive CTE starter med rodknuderne. At beregne den materialiserede sti for en rodknude er trivielt ligetil, det er selve knudepunktets ID. Ved næste iteration forbinder CTE rodknudepunkter med sine underknuder. Den materialiserede sti til en underordnet node CN
er sammenkædningen af den materialiserede sti til dens overordnede node PN
og id'et for noden CN
. Efterfølgende iterationer går et niveau ned på træet, indtil bladknuderne er nået.