【问题标题】:T-SQL Paging Sorting & Filtering - Filtering not WorkingT-SQL 分页排序和过滤 - 过滤不起作用
【发布时间】:2011-10-22 10:31:33
【问题描述】:

T-SQL 分页排序和过滤

我已经研究 T-SQL 存储过程几个小时了,这将使我能够检索基于指定列按 ASC 或 DESC 顺序排序的分页文章集。

我现在正在努力让存储过程根据“标题”字段的第一个字符进行过滤,并添加了以下行:

@StartAlpha nvarchar(1) = null

WHERE ((@StartAlpha IS NULL) OR (Title Like @StartAlpha + '%'))

见下文。

存储过程不再返回任何结果。我真的不知道为什么。

有人可以帮忙吗?

问候

沃尔特

USE [ABC]
GO
/****** Object:  StoredProcedure [dbo].[Get_MyArticles_Paged]    Script Date: 08/07/2011 20:41:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Get_MyArticles_Paged]

    /*Paging Total For Output*/
    @Row_Count BIGINT OUT,

    /*Paging Inputs*/
    @Page_Size INT = 10,
    @Page_Number INT = 1,

    @Sort_Column VARCHAR(100),  /* ('articleid','createdate','title','subject') */
    @Sort_Direction VARCHAR(4), /* ('ASC','DESC') */

    @StartAlpha nvarchar(1) = null

AS

BEGIN
print @StartAlpha
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    /*========================================================================
    Declare local variables
    ========================================================================*/
    DECLARE @FirstRecord int
    DECLARE @LastRecord int

    -- create a temporary space for paged result set
    DECLARE @PagedResults AS TABLE (
        [ArticleID] INT,
        [CreateDate] SMALLDATETIME,
        [Title] VARCHAR(200),
        [Subject] VARCHAR(500),
        [Row_Number] BIGINT,
        [Row_Count] BIGINT
    );

    /*========================
    Normalize Paging Parameters
    ==========================*/
    --Fix invalid input for Page Size
    SET @Page_Size = CASE 
        WHEN @Page_Size IS NULL THEN 10
        WHEN @Page_Size < 1 THEN 10
        ELSE @Page_Size
    END;

    --Fix invalid input for Page Number
    SET @Page_Number = CASE
        WHEN @Page_Number IS NULL THEN 1
        WHEN @Page_Number < 1 THEN 1
        ELSE @Page_Number
    END;

    --starting record to use.
    SET @FirstRecord = ((@Page_Number - 1) * @Page_Size) + 1

    --last record to use.
    SET @LastRecord = @FirstRecord + @Page_Size - 1

    --ensure sort column is valid in the list
    SET @Sort_Column = CASE
        WHEN LOWER(@Sort_Column) IN ('articleid','createdate','title','subject')
                THEN LOWER(@Sort_Column)
            ELSE
                'title' --default
    END

    --ensure sort direction is ASC or DESC
    SET @Sort_Direction = CASE
        WHEN LEFT(UPPER(COALESCE(@Sort_Direction, '')) + '    ', 4) = 'DESC' 
            THEN 'DESC' --explicit descending
        WHEN @Sort_Column = 'created' AND LEFT(UPPER(COALESCE(@Sort_Direction,'')) + '   ', 3) <> 'ASC' THEN
            'DESC' --default for created date
        ELSE 'ASC' --default otherwise
    END;

    /*============
    Prepare Results
    ==============*/
    WITH [MyTempArea] AS (
    SELECT TOP (@LastRecord)
            [ArticleID],
            [CreateDate],
            [Title],
            [Subject],
            ROW_NUMBER() OVER (
                ORDER BY
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='articleid'      THEN [articleid] END END ASC,
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='createdate'     THEN [createdate] END END ASC,
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='title'          THEN [title] END END ASC,
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='subject'    THEN [subject] END END ASC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='articleid'     THEN [articleid] END END DESC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='createdate'        THEN [createdate] END END DESC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='title'         THEN [title] END END DESC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='subject'   THEN [subject] END END DESC
            ) AS [Row_Number],
            COUNT(*) OVER () AS [Row_Count]
        FROM Articles
        WHERE ((@StartAlpha IS NULL) OR (Title Like @StartAlpha + '%'))  
    )

    INSERT INTO @PagedResults
    SELECT * FROM [MyTempArea] WHERE [Row_Number] >= @FirstRecord;

    /*===========
    Return Results
    =============*/
    -- @Row_Count output param
    SELECT @Row_Count = COALESCE(MAX(Row_Count), 0) FROM @PagedResults;

    -- Paged results set to return
    SELECT [ArticleID],[CreateDate],[Title],[Subject]
        FROM @PagedResults
    ORDER BY [Row_Number];

END

【问题讨论】:

  • 你能确保除了这两行之外你没有改变任何东西吗?删除它们并确保您获得结果。乍一看,它们中的任何一个似乎都没有任何问题。
  • 是的,山姆。通过删除这些行,我将返回所有行。

标签: tsql sorting filtering paging


【解决方案1】:

感谢所有提出有用建议的人。

我完全重构了存储过程,它现在可以工作了。见下文。

我不完全确定为什么原始存储过程不起作用以及为什么这个版本起作用,但我想我会与论坛分享。

再次感谢。

沃尔特。

更改程序 [dbo].[Account_ContactGetData] @CurrentPage int = null, @PageSize int = null, @SortColumn nvarchar(max) = null, @SortDirection varchar(5), @StartAlpha nvarchar(1) = null 以调用者身份执行 作为 开始 设置无计数; 声明@FirstRecord int; 声明@LastRecord int; --开始使用的记录。 SET @FirstRecord = ((@CurrentPage - 1) * @PageSize) + 1; --要使用的最后一条记录。 SET @LastRecord = @FirstRecord + @PageSize - 1; 与 ContactCTE 作为 ( 选择 [ContactID]、[DisplayName]、[FirstName]、[MiddleName]、[LastName]、 (ROW_NUMBER() OVER (排序方式) 当@SortColumn='ContactID' AND @SortDirection='DESC' THEN ContactID END DESC 时的情况, 当@SortColumn='ContactID' AND @SortDirection='ASC' THEN ContactID END ASC 时的情况, 当@SortColumn='DisplayName' AND @SortDirection='DESC' THEN DisplayName END DESC 时的情况, 当@SortColumn='DisplayName' AND @SortDirection='ASC' THEN DisplayName END ASC 时的情况, 当@SortColumn='FirstName' AND @SortDirection='DESC' THEN FirstName END DESC 时的情况, 当@SortColumn='FirstName' AND @SortDirection='ASC' THEN FirstName END ASC 时的情况, 当@SortColumn='MiddleName' AND @SortDirection='DESC' THEN MiddleName END DESC 时的情况, 当@SortColumn='MiddleName' AND @SortDirection='ASC' THEN MiddleName END ASC 时的情况, 当@SortColumn='LastName' AND @SortDirection='DESC' THEN LastName END DESC 时的情况, 当@SortColumn='LastName' AND @SortDirection='ASC' THEN LastName END ASC 时的情况 )) 作为行 从联系人 在哪里 ((@StartAlpha 为 NULL) 或 (LastName Like @StartAlpha+ '%')) ) 选择 [ContactID]、[DisplayName]、[FirstName]、[MiddleName]、[LastName] FROM ContactCTE @FirstRecord 和 @LastRecord 之间的行 结尾

【讨论】:

    【解决方案2】:

    仅基于这些要求,我会这样做:

    WHERE ((@StartAlpha IS NULL) OR (LEFT(Title, 1) = @StartAlpha))
    





    只运行这部分会得到什么? (还请说明您在参数中使用了哪些值)

    WITH [MyTempArea] AS (
    SELECT TOP (@LastRecord)
            [ArticleID],
            [CreateDate],
            [Title],
            [Subject],
            ROW_NUMBER() OVER (
                ORDER BY
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='articleid'      THEN [articleid] END END ASC,
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='createdate'     THEN [createdate] END END ASC,
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='title'          THEN [title] END END ASC,
                    CASE WHEN(@Sort_Direction = 'ASC') THEN CASE WHEN @Sort_Column='subject'    THEN [subject] END END ASC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='articleid'     THEN [articleid] END END DESC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='createdate'        THEN [createdate] END END DESC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='title'         THEN [title] END END DESC,
                    CASE WHEN(@Sort_Direction = 'DESC') THEN CASE WHEN @Sort_Column='subject'   THEN [subject] END END DESC
            ) AS [Row_Number],
            COUNT(*) OVER () AS [Row_Count]
        FROM Articles
        WHERE ((@StartAlpha IS NULL) OR (Title Like @StartAlpha + '%'))  
    )
    SELECT * FROM [MyTempArea]
    

    【讨论】:

    • 谢谢安德烈亚斯。我试过这个,它仍然不起作用。当我这样做时: SELECT * FROM Articles WHERE ((LEFT(T​​itle, 1) = 'd')) 它有效。我的 CTE 一定有问题。
    • @Walter 当您只在 CTE 中运行查询时,您是否得到任何行?
    • 是的。我返回了所有行。
    • @Walter 您正在查询SELECT * FROM [MyTempArea] WHERE [Row_Number] &gt;= @FirstRecord;,但在您的示例代码中@FirstRecord 为空?
    • @Andreas...SET @FirstRecord = ((@Page_Number - 1) * @Page_Size) + 1 ?它就在 SP 中
    【解决方案3】:

    @Andreas LEFT(Title, 1) 语法会比同类比较执行得更好...但是使用同类,这应该可以:

    WHERE (Title Like isnull(@StartAlpha, '') + '%')
    

    OR 与 null 的结合让我感到紧张。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      相关资源
      最近更新 更多