Bei einer hierarchischen Tabelle wie dieser:
CREATE TABLE [dbo].[btree]
(
id INT PRIMARY KEY
, parent_id INT REFERENCES [dbo].[btree] ([id])
, name NVARCHAR(20)
);
Ich möchte die gesamte Baumstruktur erhalten.
Verwenden Sie zum Beispiel diese Daten:
INSERT INTO [btree] VALUES (1, null, '1 Root');
INSERT INTO [btree] VALUES (2, 1, '1.1 Group');
INSERT INTO [btree] VALUES (3, 1, '1.2 Group');
INSERT INTO [btree] VALUES (4, 2, '1.1.1 Group');
INSERT INTO [btree] VALUES (5, 2, '1.1.2 Group');
INSERT INTO [btree] VALUES (6, 3, '1.2.1 Group');
INSERT INTO [btree] VALUES (7, 3, '1.2.2 Group');
INSERT INTO [btree] VALUES (8, 4, '1.1.1.1 Items');
INSERT INTO [btree] VALUES (9, 4, '1.1.1.2 Items');
INSERT INTO [btree] VALUES (10, 5, '1.1.2.1 Items');
INSERT INTO [btree] VALUES (11, 5, '1.1.1.2 Items');
INSERT INTO [btree] VALUES (12, 6, '1.2.1.1 Items');
INSERT INTO [btree] VALUES (13, 6, '1.2.1.2 Items');
INSERT INTO [btree] VALUES (14, 7, '1.2.2.1 Items');
Ich möchte erhalten:
+----+-----------+---------------------+
| id | parent_id | description |
+----+-----------+---------------------+
| 1 | NULL | 1 Root |
| 2 | 1 | 1.1 Group |
| 4 | 2 | 1.1.1 Group |
| 8 | 4 | 1.1.1.1 Items |
| 9 | 4 | 1.1.1.2 Items |
| 5 | 2 | 1.1.2 Group |
| 10 | 5 | 1.1.2.1 Items |
| 11 | 5 | 1.1.2.2 Items |
| 3 | 1 | 1.2 Group |
| 6 | 3 | 1.2.1 Group |
| 12 | 6 | 1.2.1.1 Items |
| 13 | 6 | 1.2.1.2 Items |
| 7 | 3 | 1.2.2 Group |
| 14 | 7 | 1.2.2.1 Items |
+----+-----------+---------------------+
Ich rufe Datensätze mit einer rekursiven Abfrage wie der folgenden ab:
;WITH tree AS
(
SELECT c1.id, c1.parent_id, c1.name, [level] = 1
FROM dbo.[btree] c1
WHERE c1.parent_id IS NULL
UNION ALL
SELECT c2.id, c2.parent_id, c2.name, [level] = tree.[level] + 1
FROM dbo.[btree] c2 INNER JOIN tree ON tree.id = c2.parent_id
)
SELECT tree.level, tree.id, parent_id, REPLICATE(' ', tree.level - 1) + tree.name AS description
FROM tree
OPTION (MAXRECURSION 0)
;
Und das ist das aktuelle Ergebnis:
+----+-----------+---------------------+
| id | parent_id | description |
| 1 | NULL | 1 Root |
| 2 | 1 | 1.1 Group |
| 3 | 1 | 1.2 Group |
| 6 | 3 | 1.2.1 Group |
| 7 | 3 | 1.2.2 Group |
| 14 | 7 | 1.2.2.1 Items |
| 12 | 6 | 1.2.1.1 Items |
| 13 | 6 | 1.2.1.2 Items |
| 4 | 2 | 1.1.1 Group |
| 5 | 2 | 1.1.2 Group |
| 10 | 5 | 1.1.2.1 Items |
| 11 | 5 | 1.1.1.2 Items |
| 8 | 4 | 1.1.1.1 Items |
| 9 | 4 | 1.1.1.2 Items |
+----+-----------+---------------------+
Ich kann nicht herausfinden, wie ich es nach Ebenen ordnen soll.
Gibt es eine Möglichkeit, für jede Unterebene einen Rang festzulegen?
Ich habe eine eingerichtet Rextester
quelle
c2.id
durch eine row_number ersetzt und links aufgefüllt werden, damit alle Teile gleich lang sind. Andernfalls funktioniert es nicht für alle Daten. Ersetzen Sie einfach 2 durch 55 in den Daten und die Reihenfolge ändert sichPath
mit einer kleinen Korrektur bearbeitet , um Polsterung hinzuzufügen.Schummeln, nur ein bisschen;) Schau ma, keine Rekursion!
Getestet bei rextester.com
Natürlich ist das oben Genannte eher begrenzt. Es funktioniert nur unter den Voraussetzungen:
name
Spalte hat (im ersten Teil) den tatsächlichen "Pfad" gespeichert.CAST .. AS int
wird nur benötigt, wenn die Teile Zahlen sind.Erläuterung: Der Code verwendet die Funktion
PARSENAME()
, die hauptsächlich dazu dient, einen Objektnamen in vier Teile aufzuteilen:Beachten Sie, dass die Reihenfolge umgekehrt ist. Als Beispiel erhalten
PARSENAME('dbo.btree', 2)
wir'dbo'
als Ergebnis. Mit 3 erhalten wir NULL (deshalbREVERSE()
wird das zweimal im Code verwendet. Andernfalls würden wir die Nullen am Anfang erhalten. Das'1.2'
würde analysiert,null, null, 1, 2
solange wir wollen1, 2, null, null
. )Fazit: Nach all dem sollte ich hinzufügen, dass die Antwort von Bob Campbel der richtige Weg ist, da sie allgemeiner ist und (in der Spalte "Pfad" im Ergebnis) die Pfadhierarchie erzeugt, die dann für die verwendet werden kann
ORDER BY
.Andere Optionen, die Sie in Betracht ziehen können - wenn die Größe der Tabelle größer wird und die rekursive Lösung langsam wird -, bestehen darin, den Pfad tatsächlich in einer separaten Spalte (in einem für die Bestellung geeigneten Format, dh mit Auffüllung) zu speichern oder das bereitgestellte zu verwenden
HierarchyID
Typ, der genau für diesen Anwendungsfall ist, hierarchische Daten.quelle
name
Kann in diesem Fall leider nicht verwendet werden. Ich werde die ganze Nacht brauchen, um es zu entziffern. Könnte ich eine Erklärung haben?name
einen Pfad (mit Text) speichert'order173.palletA27.box9'.bag3A
, könnten Sie den Code trotzdem verwenden (entfernen Sie einfach die Casts zu int). In jedem Fall ist die Abfrage von BenCambell der richtige Weg.