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 )
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
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;
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).
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;