2012-04-16 9 views
6

Oto przykład struktura tabeli:Jak pokazują rekurencyjną parentId w pojedynczej kolumny w SQL

ID Name  ParentID 
----------------------- 
1  Ancestor  NULL 
2  GrandFather 1 
3  GrandMother 1 
4  Child   3 

Próbuję napisać kwerendę, która wróci

ID  Name  Family 
---------------------------- 
1  Ancestor 
2  GrandFather Ancestor 
3  GrandMother Ancestor 
4  Child  Ancestor^GrandMother 

Tricky część jest taka, że ​​chcę pokazać rodzinę wszystkich rzędów w kolejności od góry do dołu.

Jeśli ktoś może wskazać mi w dobrym kierunku, to należy zauważyć :)

EDIT :: To jest prawdziwa zapytań, ale wynika z tego samego pomysłu. zwraca błąd na linii: marketparent.family + '^' + t2.marketGroupName bo mogę to znaleźć marketparent

WITH marketparent (marketGroupID,parentGroupID, marketGroupName,family) 
AS 
(
SELECT marketGroupID, 
     parentGroupID, 
     marketGroupName, 
     '' as family 
FROM EVE.dbo.invMarketGroups 
WHERE parentGroupID IS NULL 
UNION ALL 

    SELECT t2.parentGroupID, 
    t2.marketGroupID, 
    t2.marketGroupName, 
    marketparent.family + '^'+ t2.marketGroupName 
    FROM EVE.dbo.invMarketGroups as t2 
    INNER JOIN marketparent as mp 
    ON mp.marketGroupID = t2.parentGroupID 
) 

-- Statement using the CTE 

SELECT TOP 10 * 
FROM marketparent; 
+3

Rozwiązanie będzie zależeć od używanego DBMS. SQL Server, Oracle, MySQL lub ....? –

+0

Używam SQL Server 2008 – darthun08

+0

Użyj aliasu 'mp' zamiast' marketparent'. –

Odpowiedz

5

Ty nie określił swoich DBMS, więc jestem zakładając PostgreSQL

WITH RECURSIVE fam_tree (id, name, parent, family) as 
(
    SELECT id, 
     name, 
     parentid, 
     ''::text as family 
    FROM the_unknown_table 
    WHERE parent IS NULL 

    UNION ALL 

    SELECT t2.id, 
     t2.name, 
     t2.parentid, 
     fam_tree.family || '^' || t2.name 
    FROM the_unknown_table t2 
    INNER JOIN fam_tree ON fam_tree.id = t2.parentid 
) 
SELECT * 
FROM fam_tree; 

Jest to standardowy kod SQL (z wyjątkiem modelu typograficznego ::text), który powinien działać z niewielkimi zmianami na większości nowoczesnych systemów DBMS.

Edit:

Dla SQL Server trzeba by zastąpić standardową postacią concatention z Microsoft nie standar + (i trzeba usunąć recursive słowa kluczowego, które są wymagane przez normy, ale z jakiegoś dziwnego powodu odrzucone przez SQL Server)

WITH fam_tree (id, name, parent, family) as 
(
    SELECT id, 
     name, 
     parentid, 
     '' as family 
    FROM the_unknown_table 
    WHERE parent IS NULL 

    UNION ALL 

    SELECT t2.id, 
     t2.name, 
     t2.parentid, 
     fam_tree.family + '^' + t2.name 
    FROM the_unknown_table t2 
    INNER JOIN fam_tree ON fam_tree.id = t2.parentid 
) 
SELECT * 
FROM fam_tree; 
+0

teraz, jeśli chcę wygenerować rodzinę wiersza, który znajduje się w innej tabeli, ale ma obcy klucz do tej tabeli, czy mogę po prostu dodać jakiś kod w ostatnim zapytaniu, czy muszę włożyć coś w Z? – darthun08

+0

fam_tree.family + '^' + t2.name zwraca błąd: Wieloczęściowy identyfikator "fam_tree.family" nie może być powiązany. Jest tak prawdopodobnie dlatego, że nie podałem prawidłowego języka w moim pytaniu. Używam serwera MS SQL Server 2008, a co do reszty, nie wiem, jakich informacji potrzebujesz: P – darthun08

+0

@ user1336586: hmm, 'fam_tree.family + '^' + t2.name' powinno działać dla wszystkich Wiem. Ponieważ nie mam twoich stołów, zakładam jakąś literówkę. Spróbuj usunąć definicję kolumny w części z: 'z fam_tree jako (...' ' –

0

można użyć rekurencyjnej Common Table Expression.

declare @T table 
(
    ID int, 
    Name nvarchar(15), 
    ParentID int 
); 

insert into @T values 
(1,  N'Ancestor',  NULL), 
(2,  N'GrandFather', 1), 
(3,  N'GrandMother', 1), 
(4,  N'Child',   3); 

with C as 
(
    select T.ID, 
     T.Name, 
     T.ParentID, 
     cast(N' ' as nvarchar(max)) as Family 
    from @T as T 
    where T.ParentID is null 
    union all 
    select T.ID, 
     T.Name, 
     T.ParentID, 
     C.Family+'^'+C.Name 
    from @T as T 
    inner join C 
     on T.ParentID = C.ID 
) 
select C.ID, 
     C.Name, 
     stuff(C.Family, 1, 2, '') as Family 
from C; 
+0

dziękuję bardzo, spróbuję, że – darthun08

+0

@user zrobił to dla ciebie? Widzę, że miałeś pewne problemy z zaakceptowaną odpowiedzią, o której, jak sądzę, zadbano w mojej odpowiedzi. –

+0

nie, to nie zadziałało. Znalazłem inne rozwiązanie, w którym tworzę nową tabelę i aktualizuję wartości w sposób iteracyjny. Jeśli masz czas, poszukaj mojego nowego posta, nadal potrzebuję pomocy w tej samej sprawie. – darthun08

0
select T.ID, T.Name, (select name from table where ID=T.ParentID)as Family 
from table T 
+0

Twoje zapytanie wydaje się zwracać tylko nazwę nadrzędną każdego wiersza. to miła próba, ale szukam pełnej ścieżki :) – darthun08

Powiązane problemy