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_NUMBER
和BETWEEN
对于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。