如何参考一次CTE两次?

Nat*_*ley 25 t-sql sql-server common-table-expression sql-server-2008

我有一个非常胖的公用表表达式,其中包含行号,以便我可以返回分页结果集.我还希望在分页结果集之前返回与查询匹配的记录总数.

with recs as (select *, row_number() over (order by id) as rownum from ......)
select * from recs where rownum between @a and @b .... select count(*) from recs
Run Code Online (Sandbox Code Playgroud)

显然我上面的查询是不完整的,但它只是为了说明我的观点.我想要一页结果和匹配总数.如何在不必复制和粘贴整个20+线CTE的情况下完成此操作?

Abe*_*ler 19

不要以为你可以.来自MSDN

公用表表达式(CTE)可以被认为是在单个SELECT,INSERT,UPDATE,DELETE或CREATE VIEW语句的执行范围内定义的临时结果集.

强调"单个SELECT,INSERT,UPDATE,DELETE或CREATE VIEW语句".

这可能是您要使用临时表的情况.

CREATE TABLE #Recs
{
  .....
}
INSERT INTO #Recs
select *, row_number() over (order by id) as rownum from ......
Run Code Online (Sandbox Code Playgroud)

如果您事先不知道表的结构,可以使用此表单创建临时表:

select *, row_number() over (order by id) as rownum INTO #Recs from ......
Run Code Online (Sandbox Code Playgroud)

您将能够以上述方式使用临时表.


Jos*_*ama 19

您可以使用逗号创建多个引用上述CTE的CTE.

只是为了说明我的意思:

with recs as (
select 
    *, 
    row_number() over (order by id) as rownum from ......
    ),
counts as (
    select count(*) as totalrows from recs
)
select recs.*,count.totalrows
from recs
cross apply counts 
where rownum between @a and @b .... 
Run Code Online (Sandbox Code Playgroud)

这不是一个好的解决方案.

我发现在CTE中计算总计数而不计算记录的最佳解决方案在本文中进行了描述.

DECLARE @startRow INT; SET @startrow = 50;
WITH cols
AS
(
    SELECT table_name, column_name, 
        ROW_NUMBER() OVER(ORDER BY table_name, column_name) AS seq, 
        ROW_NUMBER() OVER(ORDER BY table_name DESC, column_name desc) AS totrows
    FROM [INFORMATION_SCHEMA].columns
)
SELECT table_name, column_name, totrows + seq -1 as TotRows
FROM cols
WHERE seq BETWEEN @startRow AND @startRow + 49
ORDERBY seq
Run Code Online (Sandbox Code Playgroud)