SQL 多次使用一个 CTE
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10196808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use one CTE many times
提问by gigi
I have this, and i get an error at set total. Why can't i access a cte many times?
我有这个,但在设置总数时出现错误。为什么我不能多次访问 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 l.Id=@idleague
)
SELECT Id, Name
FROM CTEPlayers c
WHERE RowNumber>@pageSize*(@pageNumber-1) AND RowNumber<@pageSize*@pageNumber;
SET @total = ( SELECT COUNT(*) FROM CTEPlayers )
回答by JNK
A CTE
is basically a disposable view. It only persists for a single statement, and then automatically disappears.
ACTE
基本上是一次性视图。它只持续一个语句,然后自动消失。
Your options include:
您的选择包括:
Redefine the
CTE
a second time. This is as simple as copy-paste fromWITH...
through the end of the definition to before yourSET
.Put your results into a
#temp
table or a@table
variableMaterialize the results into a real table and reference that
Alter slightly to just
SELECT COUNT
from your CTE:
CTE
第二次重新定义。这就像从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 l.Id=@idleague
回答by om471987
None of the above answers are correct... You can execute CTE once and achieve the result you want.. here is the query
以上答案都不正确...您可以执行一次 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 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;
回答by Lucero
A CTE is, per definition, only valid for one statement.
根据定义,CTE 仅对一个语句有效。
You can create an inline table-valued functionand then use this as often as you like. The inline function does what the name suggest; its query gets to be part of the query using it (in contrast to non-inline functions which are executed separately and used as a rowset).
您可以创建一个内联表值函数,然后随意使用它。内联函数顾名思义;它的查询成为使用它的查询的一部分(与单独执行并用作行集的非内联函数相反)。
回答by Arun Prasad E S
Using CTE Multiple Times to collect Data
多次使用 CTE 收集数据
;with CTEReminder AS
(
Select r.ReminderID,r.IsVerificationRequired from ReminderTbl r -- main table
),
FileTaskCountTempTbl as
(
select COUNT(t.ReminderID) as FileTaskCount -- getting first result
from TaskTbl t
left join CTEReminder r on t.ReminderID = r.ReminderID
),
FollowUpCountTempTbl as
(
select COUNT(f.FollowUpID) as Total -- getting second result
from FollowUpTbl f --cte not used here
),
MachineryRegularTaskCountTempTbl as
(
select COUNT(t.ReminderID) as TotalCount -- getting third result
from TaskTbl t
left join CTEReminder r on t.ReminderID = r.ReminderID
),
FinalResultTempTbl as
(
select COUNT(t.ReminderID) as MachineryTaskCount, -- getting fourth result
(select * from MachineryRegularTaskCountTempTbl ) as MachineryRegularTaskCount, -- Combining earlier results to last query
(select * from FollowUpCountTempTbl ) as FollowUpCount, -- Combining earlier results to last query
(select * from FileTaskCountTempTbl ) as FileTaskCount -- Combining earlier results to last query
from TaskTbl t
left join CTEReminder r on t.ReminderID = r.ReminderID
)
select * from FinalResultTempTbl
回答by Mushfiq Shaikh
Store the output in temporary table along-with the total count; set the output variable value and return the required columns from temporary table
将输出与总计数一起存储在临时表中;设置输出变量值并从临时表中返回所需的列
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
),
TotalCounter(TotalRecords) as
(select count(1) from CTEPlayers)
SELECT Id, Name, TotalRecords(select TotalRecords from TotalCounter) into #tmp
FROM CTEPlayers c
WHERE RowNumber>@pageSize*(@pageNumber-1) AND RowNumber<@pageSize*@pageNumber;
SET @total = ( SELECT TotalRecords FROM #tmp)
select Id, Name from $tmp
drop table #tmp
回答by Hugo Valer
In this case, I use this:
在这种情况下,我使用这个:
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;