2015-08-05 45 views
10

Zakładając mam tej tabeli: (c jest dzieckiem rodziców p)Wyświetlanie uporządkowanych wierszy hierarchii na serwerze SQL?

c p 
------ 
40 0 
2 3 
2 40 
3 1 
7 2 
1 0 

Gdzie (0 oznacza korzeń) - Chcę kolejności wybierz, aby być wyświetlane jako:

c b 
------ 
1 0 
3 1 
2 3 
40 0 
2 40 
7 2 

to Ponieważ mamy 2 korzenie (1,40) i 1 < 40.

Tak więc zaczynamy od 1, a następnie wyświetlamy poniżej - wszystkie to potomkowie.

Następnie przejdziemy do 40. ta sama logika ponownie.

enter image description here

Pytanie:

Jak mogę to zrobić?

jakie udało się wyświetlić to rekurencyjnie + znalezienie poziomie hierarchii * (nie wiem, czy to pomaga choć) *

WITH cte(c, p) AS (
    SELECT 40, 0 UNION ALL 
    SELECT 2,3 UNION ALL 
    SELECT 2,40 UNION ALL 
    SELECT 3,1 UNION ALL 
    SELECT 7,2 UNION ALL 
    SELECT 1,0 
    ) , cte2 AS(
     SELECT c, 
       p, 
       PLevel = 1 
     FROM cte 
     WHERE p = 0 
     UNION ALL 
     SELECT cte.c, 
       cte.p, 
       PLevel = cte2.PLevel + 1 
     FROM cte 
       INNER JOIN cte2 
        ON cte2.c = cte.p 
    ) 

SELECT * 
FROM cte2 

Full SQL fiddle

Odpowiedz

8

Masz prawie to zrobił. Wystarczy dodać rank, aby zidentyfikować każdą grupę, a następnie posortować dane na niej.

Ponadto, ponieważ pracujesz z bardziej złożoną hierarchią, musimy zmienić wartość [level]. In nie jest teraz liczbą, podaj pełną ścieżkę bieżącego elementu do rodzica. Gdzie \ oznacza rodzica. Na przykład następujący ciąg:

\ 1 \ 5 \ 4 \ 1

reprezentuje hierarchię poniżej:

1 
    --> 5 
     --> 4 
      --> 1 

mi się pomysł z hierarchyid typu. Możesz rozważyć przechowywanie hierarchii, używając go, ponieważ ma przydatne funkcje wbudowane do pracy z takimi strukturami.


Oto pełna przykład pracy z nowymi danymi:

DECLARE @DataSource TABLE 
(
    [c] TINYINT 
    ,[p] TINYINT 
); 

INSERT INTO @DataSource ([c], [p]) 
VALUES (1,0) 
     ,(3, 1) 
     ,(2, 3) 
     ,(5,1) 
     ,(7, 2) 
     ,(40, 0) 
     ,(2, 40); 

WITH DataSource ([c], [p], [level], [rank])AS 
(
    SELECT [c] 
      ,[p] 
      ,CAST('/' AS VARCHAR(24)) 
      ,ROW_NUMBER() OVER (ORDER BY [c] ASC) 
    FROM @DataSource 
    WHERE [p] = 0 
    UNION ALL 
    SELECT DS.[c] 
      ,DS.[p] 
      ,CAST(DS1.[level] + CAST(DS.[c] AS VARCHAR(3)) + '/' AS VARCHAR(24)) 
      ,DS1.[rank] 
    FROM @DataSource DS 
    INNER JOIN DataSource DS1 
     ON DS1.[c] = DS.[p] 
) 
SELECT [c] 
     ,[p] 
FROM DataSource 
ORDER BY [Rank] 
     ,CAST([level] AS hierarchyid); 

enter image description here

Ponownie, należy zwrócić uwagę na węźle (7,2) który uczestniczy w dwóch grupach (nawet w swoim przykładzie) . Sądzę, że to tylko przykładowe dane i masz sposób na zdefiniowanie miejsca, w którym powinien być włączony węzeł.