对 SQL Server 2005 结果进行分页
-
08-06-2019 - |
题
如何在 SQL Server 2005 中对结果进行分页?
我在 SQL Server 2000 中尝试过,但没有可靠的方法来做到这一点。我现在想知道SQL Server 2005是否有任何内置方法?
分页的意思是,例如,如果我按用户名列出用户,我希望能够只返回前 10 条记录,然后返回接下来的 10 条记录,依此类推。
任何帮助将非常感激。
解决方案
您可以使用 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
其他提示
如果您试图在一个语句中获取它(总计加上分页)。您可能需要探索 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
对此接受的答案实际上对我不起作用......我必须再跳一圈才能让它发挥作用。
当我尝试回答时
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
然后就成功了。
当我需要进行分页时,我通常也会使用临时表。您可以使用输出参数返回记录总数。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
这是我对分页所做的操作:我所有需要分页的大型查询都被编码为插入到临时表中。临时表有一个标识字段,其作用方式与上面提到的 row_number() 类似。我将临时表中的行数存储在输出参数中,以便调用代码知道总共有多少条记录。调用代码还指定它想要哪个页面,以及每页有多少行,这些都是从临时表中选择的。
这样做的一个很酷的事情是,我还有一个“导出”链接,允许您从应用程序中每个网格上方以 CSV 形式返回的报告中获取所有行。此链接使用相同的存储过程:您只需返回临时表的内容,而不执行分页逻辑。这安抚了那些讨厌分页并希望看到的用户 一切, ,并希望以一百万种不同的方式对其进行排序。