41

如何在 SQL Server 2005 中对结果进行分页?

我在 SQL Server 2000 中尝试过,但没有可靠的方法来做到这一点。我现在想知道 SQL Server 2005 是否有任何内置方法?

我所说的分页是指,例如,如果我按用户名列出用户,我希望能够只返回前 10 条记录,然后是接下来的 10 条记录,依此类推。

任何帮助将非常感激。

4

6 回答 6

35

你可以使用the Row_Number()函数。其用法如下:

SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users

它将从中产生一个结果集,其中包含一个RowID可用于在其间进行分页的字段。

SELECT * 
FROM 
    ( SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
      FROM Users 
    ) As RowResults
WHERE RowID Between 5 AND 10

ETC

于 2008-08-05T20:59:21.563 回答
13

如果您试图在一个语句中获取它(总数加上分页)。您可能需要探索 SQL Server 对 partition by 子句的支持(ANSI SQL 术语中的窗口函数)。在 Oracle 中,语法就像上面使用 row_number() 的示例一样,但我还添加了一个 partition by 子句来获取分页中返回的每一行包含的总行数(总行数为 1,262):

SELECT rn, total_rows, x.OWNER, x.object_name, x.object_type
FROM (SELECT COUNT (*) OVER (PARTITION BY owner) AS TOTAL_ROWS,
         ROW_NUMBER () OVER (ORDER BY 1) AS rn, uo.*
         FROM all_objects uo
         WHERE owner = 'CSEIS') x
WHERE rn BETWEEN 6 AND 10

请注意,我有 where owner = 'CSEIS' 并且我的分区在所有者上。所以结果是:

RN  TOTAL_ROWS  OWNER   OBJECT_NAME            OBJECT_TYPE
6   1262    CSEIS   CG$BDS_MODIFICATION_TYPES   TRIGGER
7   1262    CSEIS   CG$AUS_MODIFICATION_TYPES   TRIGGER
8   1262    CSEIS   CG$BDR_MODIFICATION_TYPES   TRIGGER
9   1262    CSEIS   CG$ADS_MODIFICATION_TYPES   TRIGGER
10  1262    CSEIS   CG$BIS_LANGUAGES            TRIGGER
于 2008-08-14T17:15:31.997 回答
5

对此接受的答案实际上对我不起作用......我不得不再跳一圈才能让它工作。

当我尝试答案时

SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
WHERE RowID Between 0 AND 9

它失败了,抱怨它不知道 RowID 是什么。

我不得不将它包装在这样的内部选择中:

SELECT * 
FROM
    (SELECT
    Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
    FROM Users
    ) innerSelect
WHERE RowID Between 0 AND 9

然后它起作用了。

于 2009-04-15T17:56:08.677 回答
2

当我需要进行分页时,我通常也会使用临时表。您可以使用输出参数来返回记录总数。select 中的 case 语句允许您对特定列上的数据进行排序,而无需求助于动态 SQL。

--Declaration--

--Variables
@StartIndex INT,
@PageSize INT,
@SortColumn VARCHAR(50),
@SortDirection CHAR(3),
@Results INT OUTPUT

--Statements--
SELECT @Results = COUNT(ID) FROM Customers
WHERE FirstName LIKE '%a%'

SET @StartIndex = @StartIndex - 1 --Either do this here or in code, but be consistent
CREATE TABLE #Page(ROW INT IDENTITY(1,1) NOT NULL, id INT, sorting_1 SQL_VARIANT, sorting_2 SQL_VARIANT)
INSERT INTO #Page(ID, sorting_1, sorting_2)
SELECT TOP (@StartIndex + @PageSize)
    ID,
    CASE
        WHEN @SortColumn='FirstName' AND @SortDirection='ASC' THEN CAST(FirstName AS SQL_VARIANT)
        WHEN @SortColumn='LastName' AND @SortDirection='ASC' THEN CAST(LastName AS SQL_VARIANT)
        ELSE NULL
    END AS sort_1,
    CASE
        WHEN @SortColumn='FirstName' AND @SortDirection='DES' THEN CAST(FirstName AS SQL_VARIANT)
        WHEN @SortColumn='LastName' AND @SortDirection='DES' THEN CAST(LastName AS SQL_VARIANT)
        ELSE NULL
    END AS sort_2
FROM (
    SELECT
        CustomerId AS ID,
        FirstName,
        LastName
    FROM Customers
    WHERE
        FirstName LIKE '%a%'
) C
ORDER BY sort_1 ASC, sort_2 DESC, ID ASC;

SELECT
    ID,
    Customers.FirstName,
    Customers.LastName
FROM #Page
INNER JOIN Customers ON
    ID = Customers.CustomerId
WHERE ROW > @StartIndex AND ROW <= (@StartIndex + @PageSize)
ORDER BY ROW ASC

DROP TABLE #Page
于 2008-09-16T16:17:24.913 回答
0

我相信你需要执行一个单独的查询来完成这一点。

使用此页面的一些帮助,我能够在以前的职位上完成此操作: DotNet 2.0 中的分页

他们也让它单独拉一个行数。

于 2008-08-05T21:05:10.863 回答
0

这是我为分页所做的:我所有需要分页的大查询都被编码为插入到临时表中。临时表有一个身份字段,其行为方式与上面提到的 row_number() 类似。我将临时表中的行数存储在输出参数中,以便调用代码知道总共有多少条记录。调用代码还指定它想要哪个页面,以及每页有多少行,这些都是从临时表中选择出来的。

这样做的好处是我还有一个“导出”链接,它允许您从我的应用程序中每个网格上方以 CSV 格式返回的报告中获取所有行。此链接使用相同的存储过程:您只需返回临时表的内容,而不是执行分页逻辑。这安抚了讨厌分页,想要查看所有内容,并希望以百万种不同方式对其进行排序的用户。

于 2008-08-13T14:16:13.813 回答