2010-11-24 10 views
2

Ich habe ein Problem mit einer T-SQL-Abfrage.T-SQL Wie bekommt man alle Elemente aus einem Baum in T-SQL?

Sagen wir, ich habe einen Kategorien-Baum (Kategorien ID)

cat_table

1 
| 
2-\ 
| 3-\ 
6 | 5 
| 4 | 
... ... 

ads_table

ad_ID 
category_ID 

natürlich die category_ID Spalte Verweise auf die ID Spalte in der cat_table

das Problem ist, wie man (Rekursive?) Alle Anzeigen aus allen Kategorien erhält, die die oberste Kategorie der ersten Kategorie ist?

Antwort

1

Sind Sie vertraut mit allgemeinen Tabellenausdrücken in SQL Server? Eine der vielen Anwendungen, die ein CTE hat, ist rekursive Abfragen.

Hier finden Sie eines der besten Artikel, die ich zu diesem Thema gefunden habe:

http://www.4guysfromrolla.com/webtech/071906-1.shtml

+0

Artikel Link sagt lesen: Die Seite kann nicht angezeigt werden, weil ein interner Serverfehler aufgetreten ist. –

+0

[Antwort] "Links zu externen Ressourcen werden empfohlen, aber bitte fügen Sie Kontext um den Link hinzu, damit Ihre Mitbenutzer eine Vorstellung davon haben, was es ist und warum es da ist. Zitieren Sie immer den relevantesten Teil eines wichtigen Links, falls das Ziel erreicht wird Site ist nicht erreichbar oder geht permanent offline. " – AndyJ

9

Versuch eines rekursive Common Table Expressions, auch bekannt als "CTE" (erhältlich in SQL Server 2005 und höher) wie folgt aus:

--go through a nested table supervisor - user table and display the chain 
DECLARE @Contacts table (id varchar(6), first_name varchar(10), reports_to_id varchar(6)) 
INSERT @Contacts VALUES ('1','Jerome', NULL) -- tree is as follows: 
INSERT @Contacts VALUES ('2','Joe' ,'1')  --      1-Jerome 
INSERT @Contacts VALUES ('3','Paul' ,'2')  --     /  \ 
INSERT @Contacts VALUES ('4','Jack' ,'3')  --    2-Joe   9-Bill 
INSERT @Contacts VALUES ('5','Daniel','3')  --   /  \    \ 
INSERT @Contacts VALUES ('6','David' ,'2')  --  3-Paul   6-David  10-Sam 
INSERT @Contacts VALUES ('7','Ian' ,'6')  -- / \   / \ 
INSERT @Contacts VALUES ('8','Helen' ,'6')  -- 4-Jack 5-Daniel 7-Ian 8-Helen 
INSERT @Contacts VALUES ('9','Bill ' ,'1')  -- 
INSERT @Contacts VALUES ('10','Sam' ,'9')  -- 

DECLARE @Root_id char(4) 

--get 2 and below 
SET @Root_id=2 
PRINT '@Root_id='+COALESCE(''''[email protected]_id+'''','null') 
;WITH StaffTree AS 
(
    SELECT 
     c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf 
     FROM @Contacts     c 
      LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id 
     WHERE [email protected]_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL) 
    UNION ALL 
     SELECT 
      s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1 
     FROM StaffTree   t 
      INNER JOIN @Contacts s ON t.id=s.reports_to_id 
    WHERE [email protected]_id OR @Root_id IS NULL OR t.LevelOf>1 
) 
SELECT * FROM StaffTree 

Ausgang:

@Root_id='2 ' 
id  first_name reports_to_id Manager_id Manager_first_name LevelOf 
------ ---------- ------------- ---------- ------------------ ----------- 
2  Joe  1    1   Jerome    1 
3  Paul  2    2   Joe    2 
6  David  2    2   Joe    2 
7  Ian  6    6   David    3 
8  Helen  6    6   David    3 
4  Jack  3    3   Paul    3 
5  Daniel  3    3   Paul    3 

(7 row(s) affected) 

Änderung @Root_id anders zu bekommen Ausgabe:

@Root_id=null 
id  first_name reports_to_id Manager_id Manager_first_name LevelOf 
------ ---------- ------------- ---------- ------------------ ----------- 
1  Jerome  NULL   NULL  NULL    1 
2  Joe  1    1   Jerome    2 
9  Bill  1    1   Jerome    2 
10  Sam  9    9   Bill    3 
3  Paul  2    2   Joe    3 
6  David  2    2   Joe    3 
7  Ian  6    6   David    4 
8  Helen  6    6   David    4 
4  Jack  3    3   Paul    4 
5  Daniel  3    3   Paul    4 

(10 row(s) affected) 
2

Es gibt eine Option Rezidivs in Baum-Browsing-Abfragen zu vermeiden. Sie können die Spalte "Pfad" zur Kategoriebaumstruktur hinzufügen. Es sollte alle Element-Ahnen-IDs enthalten, die mit einem nicht-numerischen Zeichen (wie Schrägstrich) begrenzt sind.

Zum Beispiel Ihre „ID = 4“ Kategorie Pfad so aussehen würde: „/ 1/2/3 /“ Nun, wenn Sie Ihre Anzeigen Tabelle zu den Kategorien beitreten müssen Sie wie folgt vorgehen:

select * from ads_table 
inner join cat_table on cat_table.ID = ads_table.category_ID 
where cat_table.Path like '/1/%' 

Und das ist Ihre Abfrage.

Sie können meinen mehr zu diesem Thema auf blog post

+0

Ich würde sicherlich sagen, das ist mehr bevorzugt und sitzen gut mit der Leistung .. – Damilola

+0

Was ist, wenn ein Kind zwei Elternteile hat? – Spivonious