通过此查询实现分页(跳过/获取)功能


138

我一直在尝试了解一些有关如何在SQL中实现自定义分页的知识,例如阅读诸如此类的文章

我有以下查询,它运行良好。但是我想用这个实现分页。

SELECT TOP x PostId FROM ( SELECT PostId, MAX (Datemade) as LastDate
 from dbForumEntry 
 group by PostId ) SubQueryAlias
 order by LastDate desc

我要什么

我有论坛帖子以及相关条目。我想获取包含最新添加条目的帖子,因此我可以选择最近辩论过的帖子。

现在,我希望能够获得“前10到20个最近活跃的帖子”,而不是“前10个”。

我尝试了什么

我试图将ROW函数实现为本文中的那个,但确实没有运气。

有什么想法如何实施吗?

Answers:


288

SQL Server 2012中,这非常简单

SELECT col1, col2, ...
 FROM ...
 WHERE ... 
 ORDER BY -- this is a MUST there must be ORDER BY statement
-- the paging comes here
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

如果我们想跳过ORDER BY,我们可以使用

SELECT col1, col2, ...
  ...
 ORDER BY CURRENT_TIMESTAMP
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

(我宁愿将其标记为hack,但例如NHibernate已使用它。使用明智选择的列作为ORDER BY是首选方法)

回答问题:

--SQL SERVER 2012
SELECT PostId FROM 
        ( SELECT PostId, MAX (Datemade) as LastDate
            from dbForumEntry 
            group by PostId 
        ) SubQueryAlias
 order by LastDate desc
OFFSET 10 ROWS -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

引入了新的关键字offsetfetch next(仅遵循SQL标准)。

但是我想,您没有使用SQL Server 2012,对吗?在以前的版本中,这有点困难。这是所有SQL Server版本的比较和示例:这里

因此,这可以在SQL Server 2008中工作

-- SQL SERVER 2008
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 10,@End = 20;


;WITH PostCTE AS 
 ( SELECT PostId, MAX (Datemade) as LastDate
   ,ROW_NUMBER() OVER (ORDER BY PostId) AS RowNumber
   from dbForumEntry 
   group by PostId 
 )
SELECT PostId, LastDate
FROM PostCTE
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY PostId

非常感谢!这是一个很好的答案!关于sql 2008的唯一问题。我希望ORDER BY发生在WHERE之前,因为它当前将对子集进行排序,但是我们想从整个集合中选择某些东西……有什么想法吗?:)再次感谢
Lars Holdgaard 2012年

2
如果我确实理解正确,那么您想按LastDate排序,对吗?那么我们可以通过以下方式更改OVER()子句:ROW_NUMBER()OVER(ORDER BY MAX(Datemade)desc)。并删除最后一个ORDER BY PostId。现在,CTE应该根据需要“尽快”排序。正确?
RadimKöhler2012年

1
谢谢您的帮助,关于2012示例的注释,order by是强制性的,我在没有order by子句的情况下尝试了此操作,并且出现错误“语法错误”,直到我研究MSDN语法并了解到order by是强制性的,才知道出了什么问题。
Esen 2014年

第一行是1还是0?如果WHERE 是0且是1000,WHERE RowNumber >= @Start AND RowNumber < @End那么应该在哪里获得前1000行?@Start@End
CWSpear

1
非常感谢
Mafii




-1

您可以使用嵌套查询进行分页,如下所示:

从4行分页到8行,其中CustomerId主键

SELECT Top 5 * FROM Customers
WHERE Country='Germany' AND CustomerId Not in (SELECT Top 3 CustomerID FROM Customers
WHERE Country='Germany' order by city) 
order by city;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.