【问题标题】:Implement paging (skip / take) functionality with this query使用此查询实现分页(跳过/获取)功能
【发布时间】:2012-10-24 14:49:57
【问题描述】:

我一直在尝试了解如何在 SQL 中实现自定义分页,例如阅读articles like this one

我有以下查询,效果很好。但我想用这个实现分页。

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 函数,但真的没有运气。

有什么想法可以实现吗?

【问题讨论】:

    标签: sql sql-server join pagination


    【解决方案1】:

    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 版本的比较和示例:here

    所以,这可以在 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 之前,因为它目前会对子集进行排序,但我们想从整个集合中选择一些东西......有什么想法吗? :) 再次感谢
    • 如果我的理解正确,您希望按 LastDate 排序,对吗?然后我们可以这样更改 OVER() 子句:ROW_NUMBER() OVER (ORDER BY MAX(Datemade) desc)。 并删除最后一个 ORDER BY PostId。现在 CTE 应该根据需要“尽快”排序。对吗?
    • 谢谢你的帮助,关于 2012 样本的注释,order by 是强制性的,我在没有 order by 子句的情况下尝试这个并且得到错误“不正确的语法”直到我查看 MSDN 才知道出了什么问题语法并了解到 order by 是强制性的。
    • 第一行是1还是0?如果@Start 为0 且@End 为1000,WHERE 是否应为WHERE RowNumber &gt;= @Start AND RowNumber &lt; @End 以获得前1000 行?
    • @CWSpear,你可以自己尝试一下……但@start = 0 将占据第一行,@end = 1000 意味着每页占据 1000 行。检查我使用的 WHERE 子句:WHERE RowNumber &gt; @Start AND RowNumber &lt;= @End
    【解决方案2】:

    为了在 SQL Server 中执行此操作,您必须按列对查询进行排序,以便指定所需的行。

    例子:

    select * from table order by [some_column] 
    offset 10 rows
    FETCH NEXT 10 rows only
    

    而且你不能在这样做的时候使用“TOP”关键字。

    您可以在此处了解更多信息: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

    【讨论】:

      【解决方案3】:
      OFFSET     10 ROWS       -- skip 10 rows
      FETCH NEXT 10 ROWS ONLY; -- take 10 rows
      

      在选择语法的末尾使用它。 =)

      【讨论】:

        【解决方案4】:

        SQL 2008

        Radim Köhler 的回答有效,但这里有一个较短的版本:

        select top 20 * from
        (
        select *,
        ROW_NUMBER() OVER (ORDER BY columnid) AS ROW_NUM
        from tablename
        ) x
        where ROW_NUM>10
        

        来源:https://forums.asp.net/post/4033909.aspx

        【讨论】:

          【解决方案5】:

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

          从 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;
          

          【讨论】:

            【解决方案6】:

            修复方法是使用 XML 编辑器修改您的 EDMX 文件,并将 ProviderManifestToken 的值从 2012 更改为 2008。我在我的 EDMX 文件的第 7 行发现了这一点。保存更改后,将使用“旧”的 SQL Server 2008 兼容语法生成分页 SQL。

            对于在这个非常古老的线程上发布答案,我深表歉意。发给像我这样的人,我今天解决了这个问题。

            【讨论】:

            • 我认为这不属于这里。问题是关于 SQL Server 查询,而您正在解释如何修改 Visual Studio 生成的文件以使用较旧的 SQL Server 实例。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-19
            • 1970-01-01
            • 2022-12-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多