当前位置:  开发笔记 > 编程语言 > 正文

使用SQL Server 2005中的ROW_NUMBER()OVER()在不同列上进行排序的分页查询

如何解决《使用SQLServer2005中的ROW_NUMBER()OVER()在不同列上进行排序的分页查询》经验,为你挑选了1个好方法。

假设我正在使用Northwind数据库,并且我希望通过包含以下参数的存储过程运行查询:

@Offset 指示分页开始的位置,

@Limit 表示页面大小,

@SortColumn 表示用于分类目的的列,

@SortDirection,表示上升或后代排序.

我的想法是对数据库进行分页,因为结果集包含数千行,因此缓存不是一个选项(并且使用VIEWSTATE甚至不被视为IMO,很糟糕).

您可能知道SQL Server 2005提供了函数ROW_NUMBER,它返回结果集的分区中的行的序号,从1开始,每个分区的第一行.

我们需要对每个返回的列进行排序(本例中为5),动态SQL不是一个选项,因此我们有两种可能:使用大量的IF ... ELSE ...10个查询,这是一个难以维护的地狱,或者具有如下查询:

WITH PaginatedOrders AS (
    SELECT
        CASE (@SortColumn + ':' + @SortDirection)
            WHEN 'OrderID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC)
            WHEN 'OrderID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC)
            WHEN 'CustomerID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID ASC)
            WHEN 'CustomerID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID DESC)
            WHEN 'EmployeeID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID ASC)
            WHEN 'EmployeeID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID DESC)
            WHEN 'OrderDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate ASC)
            WHEN 'OrderDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate DESC)
            WHEN 'ShippedDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC)
            WHEN 'ShippedDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC)
        END AS RowNumber,
        OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate
    FROM Orders
    -- WHERE clause goes here
)
SELECT
    RowNumber, OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate,
    @Offset, @Limit, @SortColumn, @SortDirection
FROM PaginatedOrders
WHERE RowNumber BETWEEN @Offset AND (@Offset + @Limit - 1)
ORDER BY RowNumber

我已经尝试了几次这样的查询,使用了不同的参数,并且它的性能实际上非常好,但它仍然看起来可能会以其他方式进行优化.

这个查询有什么问题,或者你会这样做吗?你提出了不同的方法吗?



1> Tomalak..:

简单:

SELECT
  OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate,
  @Offset, @Limit, @SortColumn, @SortDirection
FROM
  Orders
WHERE
  ROW_NUMBER() OVER 
  (
    ORDER BY
      /* same expression as in the ORDER BY of the whole query */
  ) BETWEEN (@PageNum - 1) * @PageSize + 1 AND @PageNum * @PageSize 
  /* AND more conditions ... */
ORDER BY
  CASE WHEN @SortDirection = 'A' THEN
    CASE @SortColumn 
      WHEN 'OrderID'    THEN OrderID
      WHEN 'CustomerID' THEN CustomerID
      /* more... */
    END
  END,
  CASE WHEN @SortDirection = 'D' THEN
    CASE @SortColumn 
      WHEN 'OrderID'    THEN OrderID
      WHEN 'CustomerID' THEN CustomerID
      /* more... */
    END 
  END DESC

如果选择ASC顺序,这将按NULL(DESC)排序,反之亦然.

让ROW_NUMBER()函数在同一个ORDER BY表达式上工作.

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有