web-dev-qa-db-fra.com

Utilisez un CTE plusieurs fois

J'ai ceci, et j'obtiens une erreur au total… .. Pourquoi ne puis-je pas accéder à un cte plusieurs fois?

ALTER PROCEDURE [dbo].[GetLeaguePlayers]
(
    @idleague int,
    @pageNumber int,
    @pageSize int,
    @total int OUTPUT
)
AS
WITH CTEPlayers AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY p.Name) AS RowNumber, p.Id, p.Name, t.Name AS Team
    FROM Players p INNER JOIN Teams t ON p.IdTeam=t.Id INNER JOIN Leagues l ON l.Id=t.IdLeague
    WHERE l.Id=@idleague
)
SELECT Id, Name
FROM CTEPlayers c
WHERE RowNumber>@pageSize*(@pageNumber-1) AND RowNumber<@pageSize*@pageNumber;
SET @total = ( SELECT COUNT(*) FROM CTEPlayers )
41
gigi

Une CTE est fondamentalement une vue jetable. Il ne persiste que pour une seule déclaration, puis disparaît automatiquement.

Vos options incluent:

  • Redéfinissez la CTE une seconde fois. C’est aussi simple que de copier-coller de WITH... jusqu’à la fin de la définition avant votre SET.

  • Placez vos résultats dans une table #temp ou une variable @table

  • Matérialiser les résultats dans un vrai tableau et référencer cela

  • Modifiez légèrement à juste SELECT COUNT de votre CTE:

.

SELECT @total = COUNT(*)
FROM Players p 
INNER JOIN Teams t 
    ON p.IdTeam=t.Id 
INNER JOIN Leagues l 
    ON l.Id=t.IdLeague
WHERE l.Id=@idleague
57
JNK

Aucune des réponses ci-dessus n’est correcte ... Vous pouvez exécuter CTE une fois et obtenir le résultat souhaité. Voici la requête

ALTER PROCEDURE [dbo].[GetLeaguePlayers]
(
    @idleague int,
    @pageNumber int,
    @pageSize int,
    @total int OUTPUT
)
AS
WITH CTEPlayers AS
(
    SELECT p.Id, p.Name, t.Name AS Team
    FROM Players p INNER JOIN Teams t ON p.IdTeam=t.Id INNER JOIN Leagues l ON l.Id=t.IdLeague
    WHERE l.Id=@idleague
),
TotalCount AS
(
 SELECT COUNT(*) AS Total FROM CTEPlayers
),
Final_Result AS
(
 SELECT ROW_NUMBER() OVER (ORDER BY p.Name) AS RowNumber, p.Id, p.Name, t.Name AS Team,
  (SELECT Total FROM TotalCount) AS Total
    FROM CTEPlayers
)
SELECT Id, Name, @total = Total
FROM Final_Results c
WHERE RowNumber>@pageSize*(@pageNumber-1) AND RowNumber<@pageSize*@pageNumber;
16
om471987

Un CTE est, par définition, valide pour une seule déclaration.

Vous pouvez créer une fonction inline table-values ​​ puis l’utiliser aussi souvent que vous le souhaitez. La fonction inline fait ce que son nom suggère. sa requête doit faire partie de la requête qui l'utilise (contrairement aux fonctions non intégrées qui sont exécutées séparément et utilisées comme un ensemble de lignes).

12
Lucero

Dans ce cas, j'utilise ceci:

ALTER PROCEDURE [dbo].[GetLeaguePlayers]
(
 @idleague int,
 @pageNumber int,
 @pageSize int,
 @total int OUTPUT
)
AS

WITH CTEPlayers AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY p.Name) AS RowNumber,    
        COUNT(1) OVER () AS RecordCount,
    p.Id, p.Name,   
    t.Name AS Team
    FROM Players p 
        INNER JOIN Teams t ON p.IdTeam=t.Id 
        INNER JOIN Leagues l ON l.Id=t.IdLeague
    WHERE l.Id=@idleague
)

SELECT RowNumber,
    CAST(CEILING(CAST(RecordCount AS FLOAT) / CAST(@pageSize AS FLOAT)) AS INT) PageCount,
    RecordCount,
    Id, 
    Name
FROM CTEPlayers c
WHERE RowNumber > @pageSize*(@pageNumber-1) AND RowNumber < @pageSize*@pageNumber;
0
Hugo Valer