Row Offset in SQL Server
SQL Server中是否有任何方法可以从给定的偏移量开始获取结果? 例如,在另一种类型的SQL数据库中,可以执行以下操作:
1 | SELECT * FROM MyTable OFFSET 50 LIMIT 25 |
得到结果51-75。 此构造似乎不存在于SQL Server中。
如何在不加载我不关心的所有行的情况下完成此操作? 谢谢!
我会避免使用
SQL Server 2005+
1 2 3 4 5 6 | 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中的大型结果集进行高效分页
一种更有效的大结果集寻呼方法
如果您将按顺序处理所有页面,那么只需记住上一页上看到的最后一个键值,如果存在合适的索引以允许有效地搜索它,则使用
对于选择仲裁页面,SQL Server 2005 - 2008 R2的最佳解决方案可能是
对于SQL Server 2012+,您可以使用增强的ORDER BY子句来满足此需求。
1 2 3 4 5 | SELECT * FROM MyTable ORDER BY OrderingColumn ASC OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY |
虽然这个选项的表现有多好还有待观察。
这是一种方式(SQL2000)
1 2 3 4 5 6 7 8 9 10 11 | 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)
1 2 3 4 5 6 7 8 9 | ;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 |
您可以使用
1 2 3 | SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t WHERE RowNr BETWEEN 10 AND 20 |
对于具有更多和更大数据列的表,我更喜欢:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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 ); |
-
1 2 3 | [CONDITION] can contain any WHERE clause FOR searching. [OFFSET] specifies the START, [LIMIT] the maximum results. |
它在具有大数据的表(如BLOB)上具有更好的性能,因为ROW_NUMBER函数只需查看一列,并且只返回匹配的行与所有列。
SQL Server 2012中有
如果你真的没有任何可以作为
1 2 3 | SELECT * FROM MyTable ORDER BY @@VERSION OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY |
... 要么
1 2 3 | SELECT * FROM MyTable ORDER BY (SELECT 0) OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY |
当用户没有明确指定订单时,我们在jOOQ中使用它。这将产生相当随机的顺序,而无需任何额外费用。
请参阅我的select for paginator
1 2 3 4 5 6 7 8 9 10 | 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 |
这解决了分页;)
1 2 3 | SELECT TOP 75 * FROM MyTable EXCEPT SELECT TOP 50 * FROM MyTable |
根据你的版本,你不能直接做,但你可以做一些像hacky这样的事情
1 2 3 4 5 6 7 | SELECT top 25 * FROM ( SELECT top 75 * FROM TABLE ORDER BY FIELD ASC ) a ORDER BY FIELD DESC |
其中'field'是关键。
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 |
以下将显示25条记录,不包括SQL Server 2012中的前50条记录。
1 | SELECT * FROM MyTable ORDER BY ID OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY; |
您可以将ID替换为您的要求
我使用这种技术进行分页。我没有获取所有行。例如,如果我的页面需要显示前100行,我只使用where子句获取100。 SQL的输出应该有一个唯一的键。
该表具有以下内容:
1 | ID, KeyId, Rank |
将为多个KeyId分配相同的排名。
SQL是
这是我第一次为两者传球0。第二次通过1& 14.第3次传球2和6 ....
第10记录的价值排名& ID传递给下一个
1 2 3 4 5 6 | 11 21 1 14 22 1 7 11 1 6 19 2 12 31 2 13 18 2 |
这对系统的压力最小
在SqlServer2005中,您可以执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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) |
不浪费时间订购记录的最佳方式是这样的:
1 | SELECT 0 AS tmp,Column1 FROM Table1 ORDER BY tmp OFFSET 5000000 ROWS FETCH NEXT 50 ROWS ONLY |
它只需不到一秒钟!
大表的最佳解决方案。
最简单的方法是
1 | SELECT * FROM TABLE ORDER BY OrderColumn ASC LIMIT 50,25; |
这适用于MySQL和(我认为)在其他SQL数据库中。
我一直在寻找这个答案(对于通用查询)并找到了另一种在SQL Server 2000+上使用ROWCOUNT和游标以及没有TOP或任何临时表的方法。
使用
所以你的查询将是这样的:
1 2 3 4 5 6 7 8 9 10 | 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 |