65.9K
CodeProject 正在变化。 阅读更多。
Home

简单数据分页

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.95/5 (10投票s)

2005年10月13日

2分钟阅读

viewsIcon

44159

downloadIcon

238

简单数据分页

引言

本文将向您展示如何在 Microsoft SQL Server 2000 中进行非常、非常简单的数据分页。

背景

当我开始使用 http://www.alchemi.net/ 网格处理框架进行网格处理项目时,我需要数据分页。每个节点(执行器)将从表中选择一小段数据并将其处理成报告。并且执行一个大的选择并将数据分配给执行器是不可行的,因为这只会刺激网络流量并导致远程对象出现瓶颈。

什么是数据分页?

假设您有 100,000 行数据,而您只想一次查看 1000 行数据(数据帧),那么您需要分页 100 次,每次分页您都会查看一个新的帧。

存储过程的工作原理

它选择所有数据,直到帧大小的结尾。
示例:如果您在第 5 页,并且您一次查看 100 行
因此 5*100 = 选择行 1….500

然后它交换排序以逆序显示行 500…1

最后,它只选择前 100 个并重新排序显示。

-- Page = 5
-- Frame Size = 100
SELECT  myColumn
FROM  (SELECT TOP 100 myColumn
    FROM  (SELECT TOP 500 myColumn -- Page x Frame
        FROM myTable
        ORDER BY myIDColumn) SUBSEL
    ORDER BY myIDColumn DESC) PAGESEL -- swap order
ORDER BY myIDColumn -- reorder


实际代码

上面的示例使用 myIDColumn。此列应该是每行的唯一值,例如:标识列非常适合执行此操作。如果每行的值不是唯一的,则排序可能或我可以说肯定无法正常工作。

注意: 由于 SQL 中 ORDER BY 的性质,您的排序列需要包含在您的选择中。

CREATE PROC DataPaging
 @iPage INT,
 @iFrame INT,
 @sColumns VARCHAR(4000),
 @sTable VARCHAR(4000),
 @sSortColumn VARCHAR(4000)
AS
 DECLARE @sSQL VARCHAR(4000)
 DECLARE @iCount INT 

 -- ========================================================
 -- CHECK TABLE COUNT
 -- ======================================================== 
 CREATE TABLE #Count (tablecount int) 

 -- get count insert into temp table #count
 SET @sSQL = 'INSERT INTO #Count SELECT COUNT(*) tablecount FROM ' + @sTable 
 EXEC(@sSQL)
 
 -- set variable size
 SELECT @iCount = tablecount FROM #Count 

  -- drop temp
 DROP TABLE #count   -- Check if frame count more than selection
 IF ((@iFrame * @iPage) > @iCount)
  SET @iCount = @iCount - (@iFrame * (@iPage - 1))
 ELSE
  SET @iCount = 0 
  
 -- ========================================================
 -- CREATE SQL
 -- ========================================================  IF (@iCount = 0)
  BEGIN
   SET @sSQL = 'SELECT ' + @sColumns + ' ' +
      'FROM (SELECT TOP ' + cast(@iFrame as varchar(100)) + ' ' + @sColumns +
      '   FROM (SELECT TOP ' + cast(@iPage * @iFrame as varchar(100)) + ' ' + @sColumns +
      '     FROM ' + @sTable +
      '     ORDER BY ' + @sSortColumn + ') SUBSEL' +
      '   ORDER BY ' + @sSortColumn + ' DESC) PAGESEL ' +
      'ORDER BY ' + @sSortColumn
  END
 ELSE
  BEGIN
   SET @sSQL = 'SELECT ' + @sColumns + ' ' +
      'FROM (SELECT TOP ' + cast(@iCount as varchar(100)) + ' ' + @sColumns +
      '   FROM (SELECT TOP ' + cast(@iPage * @iFrame as varchar(100)) + ' ' + @sColumns +
      '     FROM ' + @sTable +
      '     ORDER BY ' + @sSortColumn + ') SUBSEL' +
      '   ORDER BY ' + @sSortColumn + ' DESC) PAGESEL ' +
      'ORDER BY ' + @sSortColumn
  END
 
 -- ========================================================
 -- EXECUTE
 -- ========================================================
 EXEC (@sSQL) GO

查询时,我检查与传递的帧相关的表计数和计数。我这样做原因是如下:

假设您有 21 条记录,您的分页帧大小为 10,因此您需要分页 3 次…

第 1 页 = 1->10    帧大小 = 10
第 2 页 = 11->20  帧大小 = 10
第 3 页 = 21->21  帧大小 = 1


因此,当到达分页的末尾时,您选择 (页 * 帧大小) 进行交换时。  在我们的示例中,进行交换时,您将只需要选择剩余的 1 条记录,而不是通常的 10 条。

 

执行

 EXEC GenericPaging 
  1,
  500,
  'myColumn1,myColumn2,myColumn3', 
  'myTable',
  'myIDColumn'

历史

这是我对数据分页的第一次尝试,它适用于我的应用程序,并且进行了任何广泛的测试。如果您可以改进它,非常欢迎您将您的发现发送给我。

© . All rights reserved.