Используйте один CTE много раз
У меня есть это, и я получаю сообщение об ошибке.
Почему я не могу получить доступ к коте много раз?
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 [email protected]
)
SELECT Id, Name
FROM CTEPlayers c
WHERE RowNumber>@pageSize*(@pageNumber-1) AND RowNumber<@pageSize*@pageNumber;
SET @total = ( SELECT COUNT(*) FROM CTEPlayers )
Ответы
Ответ 1
A CTE
- в основном одноразовый вид. Он сохраняется только для одного утверждения, а затем автоматически исчезает.
Ваши варианты включают:
-
Повторно определите CTE
второй раз. Это так же просто, как copy-paste от WITH...
до конца определения до вашего SET
.
-
Поместите свои результаты в таблицу #temp
или переменную @table
-
Составьте результаты в реальную таблицу и ссылку, что
-
Скорее измените только SELECT COUNT
из вашего 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 [email protected]
Ответ 2
CTE, по определению, действителен только для одного оператора.
Вы можете создать встроенную функцию, ориентированную на таблицу, а затем использовать ее так часто, как вам нравится. Встроенная функция делает то, что предлагает название; его запрос становится частью запроса с его использованием (в отличие от не-встроенных функций, которые выполняются отдельно и используются как набор строк).
Ответ 3
Ни один из приведенных выше ответов не является правильным... Вы можете выполнить CTE один раз и достичь желаемого результата. Вот запрос
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 [email protected]
),
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;
Ответ 4
В этом случае я использую это:
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 [email protected]
)
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;