SQL server 2008 – Holen Sie sich die untersten verknüpften datasätze

Ich habe folgende data in meiner SQL server-database:

Id | Name | LinkedId ---+------+---------- 1 | A | 1 2 | B | 2 3 | C | 1 4 | D | 3 5 | E | 4 

Nun möchte ich eine gespeicherte Prozedur schreiben, in der der folgende datasatz angezeigt werden soll:

Hinweis : LinkedId hat die LinkedId , die mit diesem Namen LinkedId ist.

Zum Beispiel : "C" ist mit "A" verbunden

 Id | Name | LinkedId ---+------+--------- 1 | A | 1 2 | B | 2 3 | C | 1 4 | D | 1 //here instead of showing 3, it showed 1 which is the bottom most value in the tree 5 | E | 1 //same case as the above 

PROBLEM :

Für dieses Szenario nach meinem begrenzten Wissen kann ich nur an die Verwendung von JOINS (LEFT, INNER) denken, aber das wird in diesem Fall nicht genug sein, um die unten am meisten verknüpfte ID davon zu bekommen.

EDIT (AUSGANG):

Ich möchte alle Gegenstände (direkt und indirekt) mit dem Artikel "C"

 Id | Name | ---+------+ 3 | C | 4 | D | 5 | E | 

Sie könnten eine rekursive function verwenden

Eine einfache erklärende, rekursive function mit CTE ist ein common table expression , der sich beim Kakulieren einsetzt. Es enthält:

  1. Aufruf der Routine.

Der erste Aufruf des rekursiven CTE besteht aus einer oder mehreren CTE_query_definitionen, die von UNION ALL, UNION, EXCEPT oder INTERSECT betrieben werden.

Da diese Abfragedefinitionen die Basisergebnismenge der CTE-Struktur bilden, werden sie als Ankermitglieder bezeichnet.

CTE_query_definitions gelten als Anchormitglieder, wenn sie nicht auf den CTE selbst verweisen.

Alle Anchor-Member-Abfrage-Definitionen müssen vor der ersten rekursiven Member-Definition positioniert sein, und ein UNION ALL-Operator muss verwendet werden, um das letzte Anchor-Mitglied mit dem ersten rekursiven Mitglied zu verbinden.

  1. Rekursiver Aufruf der Routine.

Der rekursive Aufruf umfasst eine oder mehrere CTE_query_definitions, die von UNION ALL Operatoren verbunden sind, die auf den CTE selbst verweisen. Diese Abfragedefinitionen werden als rekursive Mitglieder bezeichnet.

  1. Kündigungskontrolle

Die Kündigung ist implizit; Rekursion stoppt, wenn keine Zeilen vom vorherigen Aufruf zurückgegeben werden.

referencelink: Rekursive Abfrage mit CTE

Einfaches Beispiel für rekursiven CTE Cte SQL server

 DECLARE @SampleData AS TABLE (Id int, Name varchar(10), LinkedId int) INSERT INTO @SampleData VALUES (1, 'A', 1), (2, 'B', 2), (3, 'C', 1),(4, 'D', 3),(5, 'A', 4) ;WITH temp AS ( SELECT sd.Id, sd.Name, sd.Id AS RootId FROM @SampleData sd WHERE sd.LinkedId = sd.Id -- Invocation of the routine, in this case it's root node of tree. UNION ALL -- Recursive invocation of the routine SELECT sd.Id, sd.Name, t.RootId AS RootId FROM temp t INNER JOIN @SampleData sd ON sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id -- Termination check: sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id. -- It make recursive query is not an infinitive loop ) SELECT t.Id, t.Name, t.RootId AS LinkedId FROM temp t OPTION (MAXRECURSION 0) -- this option remove recursive max depth, default is 100. 

Demo Link: Reesterester

Für neue Ausgabe könntest du The first invocation of the recursive CTE ändern

 ;WITH temp AS ( SELECT sd.Id, sd.Name, sd.Id AS RootId FROM @SampleData sd WHERE sd.Id = 3 UNION ALL -- Recursive invocation of the routine SELECT sd.Id, sd.Name, t.RootId AS RootId FROM temp t INNER JOIN @SampleData sd ON sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id -- Termination check: sd.LinkedId = t.Id AND sd.LinkedId <> sd.Id. -- It make recursive query is not an infinitive loop ) SELECT t.Id, t.Name, t.RootId AS LinkedId FROM temp t OPTION (MAXRECURSION 0) -- this option remove recursive max depth, default is 100. 

Sie wollen ein rekursives Verfahren:

 with cte as ( select t.id, t.name, t.linkedid, 1 as lev from t where t.linkedid = t.id union all select t.id, t.name, cte.linkedid, cte.lev + 1 from t join cte on cte.id = t.linkedid and t.linkedid <> t.id ) select id, name, linkedid from cte; 

Hier geht es in der Praxis.