SELECT * FROM
(
SELECT TOP (@pageSize) * FROM
(
SELECT TOP (@pageNumber * @pageSize) *
FROM tableName
ORDER BY columnName ASC
) AS t1
ORDER BY columnName DESC
) AS t2
ORDER BY columnName ASC
这是另一种方式(SQL2005)
;WITH results AS (
SELECT
rowNo = ROW_NUMBER() OVER( ORDER BY columnName ASC )
, *
FROM tableName
)
SELECT *
FROM results
WHERE rowNo between (@pageNumber-1)*@pageSize+1 and @pageNumber*@pageSize
SELECT col1, col2
FROM (
SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum
FROM MyTable
) AS MyDerivedTable
WHERE MyDerivedTable.RowNum BETWEEN @startRow AND @endRow
DECLARE @Limit INT
DECLARE @Offset INT
SET @Offset = 120000
SET @Limit = 10
SELECT
*
FROM
(
SELECT
row_number()
OVER
(ORDER BY column) AS rownum, column2, column3, .... columnX
FROM
table
) AS A
WHERE
A.rownum BETWEEN (@Offset) AND (@Offset + @Limit-1)
在使用 ROW_NUMBER() OVER (ORDER BY)语句时应该小心,因为性能非常差。在 ROW_NUMBER()中使用公共表表达式也是如此,这种情况甚至更糟。我正在使用下面的代码片段,它已经被证明比使用带标识的表变量提供页码稍微快一些。
DECLARE @Offset INT = 120000
DECLARE @Limit INT = 10
DECLARE @ROWCOUNT INT = @Offset+@Limit
SET ROWCOUNT @ROWCOUNT
SELECT * FROM MyTable INTO #ResultSet
WHERE MyTable.Type = 1
SELECT * FROM
(
SELECT *, ROW_NUMBER() OVER(ORDER BY SortConst ASC) As RowNumber FROM
(
SELECT *, 1 As SortConst FROM #ResultSet
) AS ResultSet
) AS Page
WHERE RowNumber BETWEEN @Offset AND @ROWCOUNT
DROP TABLE #ResultSet
如果你要按顺序处理所有的页面,那么只需记住上一页中看到的最后一个键值,并使用 TOP (25) ... WHERE Key > @last_key ORDER BY Key,如果存在合适的索引以便有效地查找,那么这可能是最好的方法——如果不存在合适的索引,那么使用 一个 API 游标可能是最好的方法。
对于选择任意页面,SQLServer2005-2008R2的最佳解决方案可能是 ROW_NUMBER和 BETWEEN
我一直在寻找这个答案有一段时间了(对于通用查询) ,并找到了在 SQL Server 2000 + 上使用 ROWCOUNT 和游标,不使用 TOP 或任何临时表的另一种方法。
使用 SET ROWCOUNT [OFFSET+LIMIT]可以限制结果,使用游标可以直接进入您希望的行,然后循环’直到结束。
所以你的问题应该是这样的:
SET ROWCOUNT 75 -- (50 + 25)
DECLARE MyCursor SCROLL CURSOR FOR SELECT * FROM pessoas
OPEN MyCursor
FETCH ABSOLUTE 50 FROM MyCursor -- OFFSET
WHILE @@FETCH_STATUS = 0 BEGIN
FETCH next FROM MyCursor
END
CLOSE MyCursor
DEALLOCATE MyCursor
SET ROWCOUNT 0
SELECT
tablename.col1,
tablename.col2,
tablename.col3,
...
FROM
(
(
SELECT
col1
FROM
(
SELECT col1, ROW_NUMBER() OVER (ORDER BY col1 ASC) AS RowNum
FROM tablename
WHERE ([CONDITION])
)
AS T1 WHERE T1.RowNum BETWEEN [OFFSET] AND [OFFSET + LIMIT]
)
AS T2 INNER JOIN tablename ON T2.col1=tablename.col1
);
-
[CONDITION] can contain any WHERE clause for searching.
[OFFSET] specifies the start,
[LIMIT] the maximum results.
对于包含大量数据(如 BLOB)的表,它的性能要好得多,因为 ROW _ NUMBER 函数只需要查看一列,并且只返回包含所有列的匹配行。
SELECT TOP @limit * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY colunx ASC) offset, * FROM (
-- YOU SELECT HERE
SELECT * FROM mytable
) myquery
) paginator
WHERE offset > @offset
使用 SQL Server 2012(11.x)及更高版本和 Azure SQL 数据库,还可以使用“ get _ row _ count _ expression”,还可以使用 ORDER BY 子句。
USE AdventureWorks2012;
GO
-- Specifying variables for OFFSET and FETCH values
DECLARE @skip int = 0 , @take int = 8;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC
OFFSET @skip ROWS
FETCH NEXT @take ROWS ONLY;