2016-03-02 2 views
5

Ich habe eine Tabelle wieWie kann ich eine Prozedur schreiben, die Ebenen i bis j oder einen Baum wie folgt bekommt?

 Users 
------------------------- 
id | ancestor_id | .... 
------------------------- 
1 | NULL  | .... 
2 |  1  | .... 
3 |  1  | .... 
4 |  3  | .... 
5 |  3  | .... 

die einen Baum wie

level 1   1 
       /\ 
    level 2  2 3 
        /\ 
    level 3   4 5 

und ich möchte erstellen ein Verfahren, das gibt den i ten bis j ten Generation von Nachkommen eines bestimmten Benutzers darstellen würde:

CREATE PROCEDURE DescendantsLevel 
    @user_id INT, 
    @i INT, 
    @j INT 
AS 
    .... 

Wenn @jNULL ist es jedoch wieder alle Nachkommen beginnend mit der Generation @i.

Beispiele:

EXEC DescendantLevel @user_id=1,@i=2,@j=NULL 

------------------------- 
id | ancestor_id | .... 
------------------------- 
1 | NULL  | .... 
2 |  1  | .... 
3 |  1  | .... 
4 |  3  | .... 
5 |  3  | .... 

und

EXEC DescendantLevel @user_id=1,@i=1,@j=2 

zurückkehren würde zurückkehren würde

 Users 
------------------------- 
id | ancestor_id | .... 
------------------------- 
1 | NULL  | .... 
2 |  1  | .... 
3 |  1  | .... 

Mehrere Fragen, die ich habe:

  • Gibt es einen besseren Wert als NULL in SQL einige Konzepte der „Unendlichkeit“ zu vertreten?
  • Wie kann ich das beschriebene Verfahren implementieren?
  • Gibt es eine bessere Möglichkeit, die Datenbank zu entwerfen, um das Verfahren zu vereinfachen?
+2

Suche rekursive Ctes. Es ist der einfachste Weg, dies zu lösen, wenn Sie dieses Design verwenden. Sie können sich auch das Modell der verschachtelten Mengen als bessere Alternative zur Adjazenzliste ansehen. –

+0

Wenn '@ i 'in Ihrem ersten Beispiel 2 ist, warum wird ID # 1 zurückgegeben? –

+0

Warum nicht eine Level-Spalte hinzufügen? Macht die Abfrage wirklich einfach. – maraca

Antwort

2

ein rekursiven CTE Verwendung:

DECLARE @test TABLE (id INT NOT NULL, ancestor_id INT NULL) 

DECLARE 
    @id INT = 1, 
    @i INT = 1, 
    @j INT = 2 

INSERT INTO @test (id, ancestor_id) 
VALUES 
    (1, NULL), 
    (2, 1), 
    (3, 1), 
    (4, 3), 
    (5, 3) 

;WITH CTE_Tree AS 
(
    SELECT 
     id, 
     ancestor_id, 
     1 AS lvl, 
     id AS base 
    FROM 
     @test 
    WHERE 
     id = @id 
    UNION ALL 
    SELECT 
     C.id, 
     C.ancestor_id, 
     P.lvl + 1 AS lvl, 
     P.base AS base 
    FROM 
     CTE_Tree P 
    INNER JOIN @test C ON C.ancestor_id = P.id 
    WHERE 
     lvl <= COALESCE(@j, 9999) 
) 
SELECT 
    id, 
    ancestor_id 
FROM 
    CTE_Tree 
WHERE 
    lvl BETWEEN @i AND COALESCE(@j, 9999) 

Diese mehr als 9999 Ebene der Rekursion auf keine angewiesen (eigentlich das Standardlimit auf Rekursion für SQL Server 100 ist, so dass mehr als 100 Level und Sie werden bekomme einen Fehler).

Verwandte Themen