具有排序和过滤功能的存储过程和分页

问题描述 投票:0回答:2

我在表中有数据,并编写了一个很好的存储过程,它具有 CTE 并且可以出色地进行分页。

我现在有一个请求,要求能够按给定的列名和特定方向(ASC/DESC)进行排序 - 问题不大,但它似乎只针对该页面执行奇怪的排序/排序,因为它只对要返回的结果集进行排序,而不是使当前页面按正确的排序顺序。

这是存储过程代码:

CREATE PROCEDURE [dbo].[sp_GetProducts] (
    @itemsPerPage int,
    @pageNumber int,
    @totalRecords int OUTPUT,   
    @sortByFieldName nvarchar(30) = 'ID',
    @sortDir nvarchar(5) = 'ASC'
)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @firstRow int
    DECLARE @lastRow int

    SELECT 
       @firstRow = (@pageNumber - 1) * @itemsPerPage + 1,
       @lastRow = (@pageNumber - 1) * @itemsPerPage + @itemsPerPage,
       @totalRecords = (SELECT COUNT(p.[SDSID]) FROM v_SDS_Summary p);

    WITH ProductSummary AS
    (
        SELECT 
           p.[ID], p.Product, p.SecondName, p.Manufacturer, p.Category,
           ROW_NUMBER() OVER (ORDER BY p.ID ASC) AS RowNumber
        FROM v_Product_Summary p
    )
    SELECT 
       RowNumber, [ID], Product, SecondName, Manufacturer, Category
    FROM 
       ProductSummary 
    WHERE 
       RowNumber BETWEEN @firstRow AND @lastRow
    ORDER BY 
       --SDSID ASC
       CASE @sortByFieldName
           WHEN 'ID' THEN CAST(ID as varchar(50))
           WHEN 'Product' THEN Product
           WHEN 'CommonName' THEN SECONDNAME
           WHEN 'Manufacturer' THEN MANUFACTURER
           WHEN 'Category' THEN CATEGORY
       END
END

当我运行它并给它一个要转到的页码时,它会返回很好的结果。

当我告诉它我想按列名称排序时,它似乎以一种我什至无法描述的奇怪方式对其进行排序。基本上,在某些人看来,如何压缩该页面上的排序仅从 a-z

Sorting issue

所以在这里,这是按 ASC 中的产品排序的,但正如您所看到的,排序不正确。从技术上讲,它似乎已排序,但这些并不是数据库中唯一的产品。大约有 3,000 种产品,按照我的指定,“a”或“b”产品肯定会显示在第 2 页上。

我做错了什么?

sql-server sql-server-2008
2个回答
1
投票

您的 CTE 始终按 ID 排序,因此它将始终使用 ID 来获取页面:

WITH ProductSummary AS
(
    SELECT p.[ID], p.Product, p.SecondName, p.Manufacturer, p.Category,
    ROW_NUMBER() OVER (ORDER BY p.ID ASC) AS RowNumber
    FROM v_Product_Summary p
)

然后,在页面上时,您可以使用以下命令对该页面的结果进行排序:

ORDER BY --SDSID ASC
CASE @sortByFieldName
    WHEN 'ID' THEN CAST(ID as varchar(50))
    WHEN 'Product' THEN Product
    WHEN 'CommonName' THEN SECONDNAME
    WHEN 'Manufacturer' THEN MANUFACTURER
    WHEN 'Category' THEN CATEGORY
END

您应该在 CTE 中使用相同的 ORDER BY 来真正按该列对所有结果进行排序:

WITH ProductSummary AS
(
    SELECT p.[ID], p.Product, p.SecondName, p.Manufacturer, p.Category,
    ROW_NUMBER() OVER (ORDER BY CASE @sortByFieldName
        WHEN 'ID' THEN CAST(ID as varchar(50))
        WHEN 'Product' THEN Product
        WHEN 'CommonName' THEN SECONDNAME
        WHEN 'Manufacturer' THEN MANUFACTURER
        WHEN 'Category' THEN CATEGORY
END ASC) AS RowNumber
    FROM v_Product_Summary p
)

0
投票

虽然这是一个很老的问题,但我想添加以下内容:

要使排序方向发挥作用,只需添加另一个具有排序方向的案例,而无需按照上述答案中的建议更改 CTE。

SELECT 
       RowNumber, [ID], Product, SecondName, Manufacturer, Category
    FROM 
       ProductSummary 
    WHERE 
       RowNumber BETWEEN @firstRow AND @lastRow
    ORDER BY 
       --SDSID ASC
       CASE @sortByFieldName
           WHEN 'ID' THEN CAST(ID as varchar(50))
           WHEN 'Product' THEN Product
           WHEN 'CommonName' THEN SECONDNAME
           WHEN 'Manufacturer' THEN MANUFACTURER
           WHEN 'Category' THEN CATEGORY
       END
       *
       CASE @sortDir
         WHEN 'DESC' THEN -1
         ELSE 1
       END
© www.soinside.com 2019 - 2024. All rights reserved.