it-swarm.com.de

Hierarchische Reihenfolge des Eltern-Kind-Baums

Ich muss Daten in SQL Server 2008 R2 folgen. SQLFiddle

Schema:

 CREATE TABLE [dbo]. [ICFilters] (
 [ICFilterID] [int] IDENTITY (1,1) NOT NULL, 
 [ParentID] [int] NOT NULL DEFAULT 0 , 
 [FilterDesc] [varchar] (50) NICHT NULL, 
 [Aktiv] [tinyint] NICHT NULL STANDARD 1, 
 EINSCHRÄNKUNG [PK_ICFilters] PRIMARY KEY CLUSTERED 
 ([ICFilterID] ASC) MIT 
 PAD_INDEX = OFF, 
 STATISTICS_NORECOMPUTE = OFF, 
 IGNORE_DUP_KEY = OFF, 
 ALLOW_ROW_LOCKS = ON, 
 ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY] 
) ON [PRIMARY] 
 
 INSERT IN [dbo]. [ICFilters] (ParentID, FilterDesc, Active) 
 Werte 
 (0, 'Produkttyp', 1), 
 (1, 'ProdSubType_1', 1), 
 (1, 'ProdSubType_2', 1), 
 (1, 'ProdSubType_3', 1), 
 (1, 'ProdSubType_4', 1), 
 (2, 'PST_1.1', 1), 
 (2, 'PST_1.2', 1), 
 (2, 'PST_1.3', 1), 
 (2, 'PST_1.4', 1), 
 (2, 'PST_1.5', 1), 
 (2, 'PST_1.6', 1), 
 (2, 'PST_1.7', 0), 
 (3, 'PST_2.1', 1), 
 (3, 'PST_2.2', 0), [._ ___.] (3, 'PST_2.3', 1), 
 (3, 'PST_2.4', 1), 
 (14, 'PST_2.2.1', 1), 
 (14, 'PST_2.2.2', 1), 
 (14, 'PST_2.2.3', 1), 
 (3, 'PST_2.8', 1) 

Tabelle:

 | ICFILTERID | ELTERN | FILTERDESC | AKTIV | 
 --------------------------------------- ------- 
 | 1 | 0 | Produkttyp | 1 | 
 | 2 | 1 | ProdSubType_1 | 1 | 
 | 3 | 1 | ProdSubType_2 | 1 | 
 | 4 | 1 | ProdSubType_3 | 1 | 
 | 5 | 1 | ProdSubType_4 | 1 | 
 | 6 | 2 | PST_1.1 | 1 | 
 | 7 | 2 | PST_1.2 | 1 | 
 | 8 | 2 | PST_1.3 | 1 | 
 | 9 | 2 | PST_1.4 | 1 | 
 | 10 | 2 | PST_1.5 | 1 | 
 | 11 | 2 | PST_1.6 | 1 | 
 | 12 | 2 | PST_1.7 | 0 | 
 | 13 | 3 | PST_2.1 | 1 | 
 | 14 | 3 | PST_2.2 | 0 | 
 | 15 | 3 | PST_2.3 | 1 | 
 | 16 | 3 | PST_2.4 | 1 | 
 | 17 | 14 | PST_2.2.1 | 1 | 
 | 18 | 14 | PST_2.2.2 | 1 | 
 | 19 | 14 | PST_2.2.3 | 1 | 
 | 20 | 3 | PST_2.8 | 1 | 

Jede Zeile hat die ID ihres übergeordneten Elements und das parentid = 0 Des Stamms. Die FilterDescs sind nur Beispielbeschreibungen, daher kann ich nicht versuchen, diese für die Bestellung zu analysieren.

Die Frage

Ist es möglich, alle Zeilen baumartig auszuwählen? Wenn das so ist, wie? Wenn ich "baumartig" sage, meine ich, rekursiv das Elternteil auszuwählen, gefolgt von allen seinen Kindern, dann allen Kindern von jedem von diesen und so weiter. Eine Tiefe erste Baumdurchquerung.

Meine Freunde und ich haben es versucht, aber wir haben keine funktionierenden Lösungen gefunden, werden es aber weiter versuchen. Ich bin ziemlich neu in SQL, also kann dies vielleicht einfach gemacht werden und ich mache die Dinge nur schwieriger als nötig.

Beispiel (gewünschte) Ausgabe:

 | ICFILTERID | ELTERN | FILTERDESC | AKTIV | 
 --------------------------------------- ------- 
 | 1 | 0 | Produkttyp | 1 | 
 | 2 | 1 | ProdSubType_1 | 1 | 
 | 6 | 2 | PST_1.1 | 1 | 
 | 7 | 2 | PST_1.2 | 1 | 
 | 8 | 2 | PST_1.3 | 1 | 
 | 9 | 2 | PST_1.4 | 1 | 
 | 10 | 2 | PST_1.5 | 1 | 
 | 11 | 2 | PST_1.6 | 1 | 
 | 12 | 2 | PST_1.7 | 0 | 
 | 3 | 1 | ProdSubType_2 | 1 | 
 | 13 | 3 | PST_2.1 | 1 | 
 | 14 | 3 | PST_2.2 | 0 | 
 | 17 | 14 | PST_2.2.1 | 1 | 
 | 18 | 14 | PST_2.2.2 | 1 | 
 | 19 | 14 | PST_2.2.3 | 1 | 
 | 15 | 3 | PST_2.3 | 1 | 
 | 16 | 3 | PST_2.4 | 1 | 
 | 20 | 3 | PST_2.8 | 1 | 
 | 4 | 1 | ProdSubType_3 | 1 | 
 | 5 | 1 | ProdSubType_4 | 1 | 
21
Archangel33

OK, genug Gehirnzellen sind tot.

SQL Fiddle

WITH cte AS
(
  SELECT 
    [ICFilterID], 
    [ParentID],
    [FilterDesc],
    [Active],
    CAST(0 AS varbinary(max)) AS Level
  FROM [dbo].[ICFilters]
  WHERE [ParentID] = 0
  UNION ALL
  SELECT 
    i.[ICFilterID], 
    i.[ParentID],
    i.[FilterDesc],
    i.[Active],  
    Level + CAST(i.[ICFilterID] AS varbinary(max)) AS Level
  FROM [dbo].[ICFilters] i
  INNER JOIN cte c
    ON c.[ICFilterID] = i.[ParentID]
)

SELECT 
  [ICFilterID], 
  [ParentID],
  [FilterDesc],
  [Active]
FROM cte
ORDER BY [Level];
25
Travis

Das obige scheint für mich nicht richtig zu funktionieren. Stellen Sie sich ein 2-Tabellen-Setup mit Facebook-Daten vor. Tabelle 1 enthält PostId + andere Felder. PostId wird automatisch inkrementiert und natürlich sortieren Sie DESC in Ihrer Benutzeroberfläche, um den neuesten Beitrag oben zu haben.

Nun zur Kommentartabelle. Tabelle 2 Diese Tabelle CommentId ist der Primärschlüssel, die automatische Nummer. In Ihrer GUI möchten Sie es als ASC anzeigen, damit es beim Lesen des Threads Sinn macht. (älteste (kleinere Zahl) oben) Weitere wichtige Schlüssel in Tabelle 2 sind: PostId (FK zurück zu Posts) und ParentId (FK to CommentId), wobei ParentId NULL ist, wenn dies der "Root" -Kommentar zu einem Post ist. Wenn jemand auf einen Kommentar antwortet, wird die parentId mit der Kommentar-ID gefüllt.
Hoffe ihr bekommt den Drift. Der CTE sieht folgendermaßen aus:

WITH  Comments
        AS ( SELECT  CommentId , ParentId, CAST(CommentId AS VARBINARY(MAX)) AS Sortkey, 0 AS Indent
             FROM    dbo.Comments
             WHERE   ParentId IS NULL AND PostId = 105
             UNION ALL
             SELECT  b.CommentId , b.ParentId,  c.Sortkey + CAST(b.CommentId AS varbinary(max))  AS Sortkey, c.Indent + 1 AS Indent
             FROM    dbo.Comments b
             INNER JOIN Comments c ON c.CommentId = b.ParentId
           )
   SELECT   *
   FROM     Comments
   ORDER BY Sortkey

Beispielausgabe

1   NULL    0x0000000000000001  0
5   1   0x00000000000000010000000000000001  1
6   5   0x000000000000000100000000000000010000000000000005  2
2   NULL    0x0000000000000002  0

In F/B-Post 105 gab es zwei Kommentare (CommentIds 1 und 2). Jemand antwortete dann auf Comment1 (CommentId 5, ParentId 1), und dann kommentierte jemand anderes diese Antwort, also auf Comment5 (CommentId 6, ParentId 6).

Und Viola, die Reihenfolge ist korrekt, unter dem Beitrag können Sie jetzt die Kommentare in der richtigen Reihenfolge anzeigen. Um die Beiträge so einzurücken, dass sie sich wie in Facebook bilden und umreißen (je tiefer das Level geht, desto mehr muss es von links begrenzt werden), habe ich auch eine Spalte namens Einrücken. Die Wurzeln sind 0 und dann haben wir in der Union c.Indent + 1 AS-Einzug. Im Code können Sie jetzt den Einzug mit 32px multiplizieren und die Kommentare in einer schönen Hierarchie und Gliederung anzeigen.

Ich sehe kein Problem darin, den Auto-Inkrement-Primärschlüssel CommentId als treibende Kraft für die Erstellung meines SortKey zu verwenden, da es eine bessere Änderung gibt, wenn Sie Datumsangaben (Kommentardatum) durcheinander bringen, als wenn Sie einen datenbankverwalteten Schlüssel durcheinander bringen, der mit +1 beginnt

1
Guss Davey
create table pc ( parent varchar(10), child varchar(10) )

insert into pc values('a','b');
insert into pc values('a','c');
insert into pc values('b','e');
insert into pc values('b','f');
insert into pc values('a','d');
Insert into pc values('b','g');
insert into pc values('c','h');
insert into pc values('c','i');
insert into pc values('d','j');
insert into pc values('f','k');
insert into pc values('x','y');
insert into pc values('y','z');
insert into pc values('m','n');

 DECLARE @parent varchar(10) = 'a';
 WITH cte AS
 (
  select null parent, @parent child, 0 as level
   union
  SELECT  a.parent, a.child , 1 as level
    FROM pc a
   WHERE a.parent = @parent
   UNION ALL
  SELECT a.parent, a.child , c.level +    1
  FROM pc a JOIN cte c ON a.parent = c.child
  )
  SELECT distinct parent, child , level
  FROM cte
  order by level, parent

Dies gibt Ihnen alle Nachkommen und das Level.
Hoffe das hilft :)

0
Wohoooo