如何参考一次CTE两次?

时间:2010-01-26 00:03:58

标签: sql-server tsql sql-server-2008 common-table-expression

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

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

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

5 个答案:

答案 0 :(得分:19)

不要以为你可以。来自MSDN

  

公用表表达式(CTE)可以   被认为是临时结果集   这是在执行中定义的   单个SELECT,INSERT的范围,   更新,删除或创建视图   言。

强调“单个SELECT,INSERT,UPDATE,DELETE或CREATE VIEW语句。”

这可能是您想要使用Temporary Table

的情况
CREATE TABLE #Recs
{
  .....
}
INSERT INTO #Recs
select *, row_number() over (order by id) as rownum from ......

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

select *, row_number() over (order by id) as rownum INTO #Recs from ......

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

答案 1 :(得分: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 .... 

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

this article中描述了我发现在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

答案 2 :(得分:4)

你可以追加一个总行数的字段,当然它会在每一行

select recs.*,totalrows = (select count(0) from recs) 
from recs

答案 3 :(得分:1)

这是最好的:

;WITH recs AS
(SELECT a,b,c,
      row_number() over (
                         ORDER BY id) AS RowNum,
                   row_number() over () AS RecordCount
FROM ......)
SELECT a,b,c,rownum,RecordCount FROM recs
WHERE rownum BETWEEN @a AND @b

答案 4 :(得分:1)

这就是我们在生产环境中处理分页(目前没有会话管理)的方法。按预期执行。

DECLARE
   @p_PageNumberRequested  int = 1,
      -- Provide -1 to retreive all pages with all the rows.
   @p_RowsPerPage          int = 25

;WITH Numbered AS (
SELECT
   ROW_NUMBER() OVER (ORDER BY YourOrdering) AbsoluteRowNumber
,  COUNT(1) OVER () TotalRows
,  YourColumns
FROM
   YourTable
),
Paged AS (
SELECT
   (AbsoluteRowNumber - 1) / @p_RowsPerPage + 1 PageNumber,
   *
FROM
   Numbered)
SELECT
   ROW_NUMBER() OVER(PARTITION BY PageNumber ORDER BY AbsoluteRowNumber) RowNumberOnPage,
   *
FROM
   Paged
WHERE
      PageNumber = @p_PageNumberRequested
   OR
      @p_PageNumberRequested = -1
ORDER BY 
   AbsoluteRowNumber