SQL Server中的行偏移

SQL Server中有没有办法从给定的偏移量开始获取结果? 例如,在另一种types的SQL数据库中,可以这样做:

SELECT * FROM MyTable OFFSET 50 LIMIT 25 

得到结果51-75。 此构造似乎不存在于SQL Server中。

我怎么能不加载所有我不关心的行呢? 谢谢!

我会避免使用SELECT * 。 指定实际上想要的列,即使它们可能都是。

SQL Server 2005+

 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 

SQL Server 2000

在SQL Server 2000中通过大型结果集高效地分页

一种更有效的通过大型结果集进行寻呼的方法

如果您将按顺序处理所有页面,则只需记住上一页中显示的最后一个键值,并使用TOP (25) ... WHERE Key > @last_key ORDER BY Key如果存在合适的索引,则TOP (25) ... WHERE Key > @last_key ORDER BY Key可以是最好的执行方法这将有效地寻找 – 或者一个API光标,如果他们没有。

为了select一个任意页面,SQL Server 2005 – 2008 R2的最佳解决scheme可能是ROW_NUMBERBETWEEN

对于SQL Server 2012+,您可以使用增强型ORDER BY子句来满足此需求。

 SELECT * FROM MyTable ORDER BY OrderingColumn ASC OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY 

虽然这个选项的performance有多好,还有待观察 。

这是一种方法(SQL2000)

 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 

这是另一种方式(SQL 2005)

 ;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 

你可以使用ROW_NUMBER()函数来得到你想要的:

 SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t WHERE RowNr BETWEEN 10 AND 20 

对于具有更多和更大数据列的表,我更喜欢:

 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. 

它在像BLOBs这样的大数据表上有更好的性能,因为ROW_NUMBER函数只需要查看一列,而只有匹配的行才会返回所有的列。

在SQL Server 2012中有OFFSET .. FETCH ,但是你需要指定一个ORDER BY列。

如果你真的没有任何明确的列,你可以作为一个ORDER BY列传递(如其他人所build议的),那么你可以使用这个技巧:

 SELECT * FROM MyTable ORDER BY @@VERSION OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY 

… 要么

 SELECT * FROM MyTable ORDER BY (SELECT 0) OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY 

当用户没有明确指定订单时,我们在jOOQ中使用它。 然后这将产生相当随机的sorting,没有任何额外的成本。

 SELECT TOP 75 * FROM MyTable EXCEPT SELECT TOP 50 * FROM MyTable 

看到我的select分页

 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 

这解决了分页;)

根据你的版本,你不能直接做,但你可以做一些像哈克一样

 select top 25 * from ( select top 75 * from table order by field asc ) a order by field desc 

其中“领域”是关键。

当使用row_number()OVER(ORDER BY)语句作为performane时,应该小心。 用row_number()更糟的是使用公用表expression式。 我正在使用以下代码片段,事实certificate,使用带有标识的表variables来提供页码会稍微快一些。

 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 

我一直在寻找这个答案一段时间(对于通用查询),并find了使用ROWCOUNT和游标,没有TOP或任何临时表在SQL Server 2000 +上的另一种方法。

使用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 

我使用这种技术进行分页。 我不抓取所有的行。 例如,如果我的页面需要显示前100行,我只用where子句获取100。 SQL的输出应该有一个唯一的键。

该表具有以下内容:

 ID, KeyId, Rank 

相同的等级将被分配给多个KeyId。

SQL是select top 2 * from Table1 where Rank >= @Rank and ID > @Id

这是我第一次通过0。 第二次传球1和14.第三次传球2和6 ….

第十个Rank&Id的值被传递给下一个

 11 21 1 14 22 1 7 11 1 6 19 2 12 31 2 13 18 2 

这将对系统造成最小的压力

在SqlServer2005中,您可以执行以下操作:

 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) 

以下将显示25条logging,不包括SQL Server 2012中的前50条logging。

 SELECT * FROM MyTable ORDER BY ID OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY; 

您可以根据您的要求replaceID

不浪费时间订购logging的最佳方式是这样的:

 select 0 as tmp,Column1 from Table1 Order by tmp OFFSET 5000000 ROWS FETCH NEXT 50 ROWS ONLY 

它只需要不到一秒钟!
大表格的最佳解决scheme。