获取记录子集以及总记录数

时间:2010-01-06 19:59:03

标签: sql-server sql-server-2008

我正在努力从SQL Server 2008返回一个记录集来进行一些分页。我一次只返回15条记录,但我需要有匹配的总数以及记录的子集。我使用了两个不同的查询,混合结果取决于我需要拉动子集的较大组中的位置。这是一个示例:

SET NOCOUNT ON;
WITH tempTable AS (
  SELECT
     FirstName
     , LastName
     , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber 
   FROM People
   WHERE 
      Active = 1
)

SELECT 
   tempTable.*     
   , (SELECT Max(RowNumber) FROM tempTable) AS Records    
FROM tempTable     
WHERE
   RowNumber >= 1
   AND RowNumber <= 15
ORDER BY
   FirstName

当我在匹配的低端返回项目时,这个查询真的很快,比如记录1到15.但是,当我开始返回记录1000 - 1015时,处理将来自在一秒钟内超过15秒。

所以我将查询更改为以下内容:

SET NOCOUNT ON;
WITH tempTable AS (
  SELECT * FROM (
     SELECT
        FirstName
        , LastName
        , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber 
        , COUNT(*) OVER(PARTITION BY NULL) AS Records
      FROM People
      WHERE 
         Active = 1
   ) derived
   WHERE RowNumber >= 1 AND RowNumber <= 15
)

SELECT 
   tempTable.*     
FROM tempTable     
ORDER BY
   FirstName

该查询在2-3秒内运行高数字返回,但也会在2-3秒内运行低数字查询。因为它为70,000多行中的每一行进行计数,所以每个请求需要更长的时间,而不仅仅是大行数。

所以我需要弄清楚如何获得一个好的行计数,以及只返回结果集中任何一点的项目子集而不会遭受如此巨大的惩罚。我可以处理高排数的2-3秒罚款,但是15太多了,而且我不愿意在人们看到的前几页上遭受缓慢的负荷。

注意:我知道在第二个例子中我不需要CTE,但这只是一个简单的例子。在生产中,在我将其过滤到我需要的15行之后,我正在进一步加入tempTable。

2 个答案:

答案 0 :(得分:8)

以下是我所做的事情(无论我返回哪条记录,它都一样快):

--Parameters include:
@pageNum int = 1,
@pageSize int = 0,



DECLARE 
    @pageStart int,
    @pageEnd int

SELECT
    @pageStart = @pageSize * @pageNum - (@pageSize - 1),
    @pageEnd = @pageSize * @pageNum;


SET NOCOUNT ON;
WITH tempTable AS (
    SELECT
        ROW_NUMBER() OVER (ORDER BY FirstName ASC) AS RowNumber,
        FirstName
        , LastName
    FROM People
    WHERE Active = 1
)

SELECT
    (SELECT COUNT(*) FROM tempTable) AS TotalRows,
    *
FROM tempTable
WHERE @pageEnd = 0
OR RowNumber BETWEEN @pageStart AND @pageEnd
ORDER BY RowNumber

答案 1 :(得分:0)

我过去没有通过确定明确的行计数来处理与此类似的情况,但是使用查询计划给出了估计的行数,有点像此链接中的第一项描述:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=108658

然后打算在范围内(从900-915)提供所要求的任何行,然后返回估计的行数,如

rows 900-915 of approx. 990

避免了计算所有行。一旦用户超出该点,我就会显示

rows 1000-1015 of approx. 1015

即。将最后请求的行作为我的新估计。