Frage

Im folgenden Code verwende ich einen rekursiven CTE (Common Table Expression) in SQL Server 2005, um zu versuchen, das übergeordnete Element der obersten Ebene einer grundlegenden hierarchischen Struktur zu finden.Die Regel dieser Hierarchie besteht darin, dass jede CustID eine ParentID hat und wenn die CustID kein übergeordnetes Element hat, dann ist ParentID = CustID und es handelt sich um die höchste Ebene.

DECLARE @LookupID int

--Our test value
SET @LookupID = 1

WITH cteLevelOne (ParentID, CustID) AS
(
        SELECT   a.ParentID, a.CustID
        FROM     tblCustomer AS a
        WHERE    a.CustID = @LookupID
    UNION ALL
        SELECT   a.ParentID, a.CustID
        FROM     tblCustomer AS a
        INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID
        WHERE c.CustID <> a.CustomerID
)

Wenn tblCustomer also so aussieht:

ParentID    CustID
5            5
1            8
5            4
4            1

Das Ergebnis, das ich aus dem obigen Code erhalte, ist:

ParentID    CustID
4            1
5            4
5            5

Was ich möchte, ist nur die letzte Zeile dieses Ergebnisses:

ParentID    CustID
5            5

Wie kann ich einfach den letzten im CTE generierten Datensatz zurückgeben (das wäre die CustID der höchsten Ebene)?

Beachten Sie auch, dass es in dieser Tabelle mehrere unabhängige CustID-Hierarchien gibt, sodass ich nicht einfach ein SELECT * FROM tblCustomer WHERE ParentID = CustID ausführen kann.Ich kann nicht nach ParentID oder CustID bestellen, da die ID-Nummer nichts mit der Position in der Hierarchie zu tun hat.

War es hilfreich?

Lösung

Wenn Sie nur die höchste Rekursionstiefe wünschen, könnten Sie dann nicht so etwas tun? Wenn Sie dann tatsächlich den CTE abfragen, suchen Sie einfach nach der Zeile mit max(Depth)?Etwa so:

DECLARE @LookupID int

--Our test value
SET @LookupID = 1;

WITH cteLevelOne (ParentID, CustID, Depth) AS
(
        SELECT   a.ParentID, a.CustID, 1
        FROM     tblCustomer AS a
        WHERE    a.CustID = @LookupID
    UNION ALL
        SELECT   a.ParentID, a.CustID, c.Depth + 1
        FROM     tblCustomer AS a
        INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID 
        WHERE c.CustID <> a.CustID
)
select * from CTELevelone where Depth = (select max(Depth) from CTELevelone)

oder, um zu adaptieren, was Trevor vorschlägt, könnte dies mit demselben CTE verwendet werden:

select top 1 * from CTELevelone order by Depth desc

Ich glaube nicht, dass CustomerID in dem von Ihnen beschriebenen Fall unbedingt das war, was Sie bestellen wollten, aber ich war mir bei der Frage auch nicht ganz klar.

Andere Tipps

Ich bin mir nicht sicher, ob ich das Problem vollständig verstehe, aber um es einfach in den Griff zu bekommen, könnten Sie Folgendes versuchen:

SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC

Das setzt voraus, dass die CustID auch wie im Beispiel in Ordnung ist und nicht so etwas wie eine GUID.

Erstens wird der CTE nicht abgeschlossen, wenn eines der übergeordneten und untergeordneten Elemente identisch ist.Da es sich um einen rekursiven CTE handelt, muss er beendet werden.Wenn die Eltern- und Kunden-ID identisch sind, wird die Schleife nicht beendet.

MSG 530, Stufe 16, Zustand 1, Zeile 15 Die Erklärung endete.Die maximale Rekursion von 100 wurde vor Abschluss der Anweisung ausgeschöpft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top