Question

Dans le code ci-dessous, j'utilise un CTE (Common Table Expression) récursif dans SQL Server 2005 pour essayer de trouver le parent de niveau supérieur d'une structure hiérarchique de base.La règle de cette hiérarchie est que chaque CustID a un ParentID et si le CustID n'a pas de parent alors ParentID = CustID et c'est le niveau le plus élevé.

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
)

Donc si tblCustomer ressemble à ceci :

ParentID    CustID
5            5
1            8
5            4
4            1

Le résultat que j'obtiens du code ci-dessus est :

ParentID    CustID
4            1
5            4
5            5

Ce que je veux, c'est juste la dernière ligne de ce résultat :

ParentID    CustID
5            5

Comment puis-je simplement renvoyer le dernier enregistrement généré dans le CTE (qui serait le CustID de niveau le plus élevé) ?

Notez également qu'il existe plusieurs hiérarchies CustID non liées dans ce tableau, je ne peux donc pas simplement faire un SELECT * FROM tblCustomer WHERE ParentID = CustID.Je ne peux pas commander par ParentID ou CustID car le numéro d'identification n'est pas lié à son emplacement dans la hiérarchie.

Était-ce utile?

La solution

Si vous voulez juste la profondeur de récursion la plus élevée, ne pourriez-vous pas faire quelque chose comme ça ? Ensuite, lorsque vous interrogez réellement le CTE, recherchez simplement la ligne avec max(Depth) ?Ainsi:

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)

ou, en adaptant ce que suggère Trevor, cela pourrait être utilisé avec le même CTE :

select top 1 * from CTELevelone order by Depth desc

Je ne pense pas que CustomerID soit nécessairement ce que vous vouliez commander dans le cas que vous avez décrit, mais je n'étais pas non plus parfaitement clair sur la question.

Autres conseils

Je ne suis pas sûr de bien comprendre le problème, mais juste pour le pirater, vous pouvez essayer :

SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC

Cela suppose que le CustID est également en ordre comme dans l'exemple, et non quelque chose comme un GUID.

Premièrement, le cte ne sera pas terminé si l'un des parents-enfants est le même.Comme il s'agit d'un CTE récursif, il doit être terminé.Ayant le parent et le client identiques, la boucle ne se terminera pas.

MSG 530, niveau 16, état 1, ligne 15 La déclaration s'est terminée.La récursivité maximale de 100 a été épuisée avant la fin de l'instruction.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top