web-dev-qa-db-fra.com

Faire une demande de CTE récursive comme une requête, mais pour de nombreux disques

J'ai une table avec une hiérarchie (avec une colonne de parentid récursive), pour un enregistrement, je sais comment obtenir le dernier enregistrement parent, avec le code suivant:

declare @Id integer

;WITH CTE AS
(
    SELECT  a.[Id],
            a.[ParentId]
    FROM    [Area] a WITH (NOLOCK)
    where a.[Id] = @Id 

    UNION ALL

    SELECT  a.[Id],
            a.[ParentId]
    FROM [Area] a WITH (NOLOCK)
    INNER JOIN CTE cte ON cte.[ParentId] = a.[Id]
)

SELECT top 1 a.[Id]
FROM CTE a
WHERE a.ParentId is null

Cela fonctionne aussi longtemps que je travaille avec un identifiant, ici @ID.

Mais je ne trouve pas un moyen de faire la même chose, mais pour une liste d'identifiants, sans utiliser de curseurs, car CTE semble être ok que lorsque vous travailliez sur un enregistrement.

Quelqu'un pourrait-il me dire à la bonne direction?

Merci beaucoup

4
PAP

En supposant que la conception de la table d'origine est un peu comme celle-ci:

CREATE TABLE dbo.Area
(
    RowID integer PRIMARY KEY,
    GroupID  integer NOT NULL,
    ParentID integer NULL,
);

Exemples de données:

INSERT dbo.Area
    (RowID, GroupID, ParentID)
VALUES 
    (1, 1, NULL), -- Root
    (2, 1, 1),
    (3, 1, 2),
    (4, 2, NULL), -- Root
    (5, 2, 4),
    (6, 2, 5),
    (7, 2, 6);

La requête CTE récursive suivante trouve des racines de la liste RowID donné dans l'ancre:

WITH R AS
(
    SELECT
        A.RowID,
        A.RowID AS OriginalRowID,
        A.ParentID
    FROM dbo.Area AS A
    WHERE
        A.RowID IN (3, 7)

    UNION ALL

    SELECT
        A.RowID,
        R.OriginalRowID,
        A.ParentID
    FROM dbo.Area AS A
    JOIN R
        ON R.ParentID = A.RowID
)
SELECT
    R.OriginalRowID,
    R.RowID
FROM R
WHERE
    R.ParentID IS NULL
ORDER BY
    R.OriginalRowID
OPTION (MAXRECURSION 0);

La sortie montre chaque fournisseur RowID et la racine de ce groupe:

Output

5
Paul White 9