【问题标题】:SQL - Retrieve data pagewiseSQL - 按页检索数据
【发布时间】:2013-09-30 13:20:36
【问题描述】:

我有一个返回联系人列表的存储过程。由于有很多联系人,并且出于性能原因,我希望以分页方式检索联系人,每个实例中仅获取 20 个联系人。

我的表单上的一个按钮可以让我转到下一页,一旦单击该按钮,我就会去获取接下来的 20 个联系人。

这是我的存储过程;

CREATE PROCEDURE [dbo].[GetAllContacts] (@searchVal VARCHAR(500))
AS
  BEGIN
      SELECT DISTINCT ( Id ) AS Id,
                      FirstName,
                      LastName,
                      Address,
                      Tel_no
      FROM   tblContact
      WHERE  ( FirstName LIKE ( '%' + @searchVal + '%' )
                OR LastName LIKE ( '%' + @searchVal + '%' ) )
      ORDER  BY LastName
  END 

如何拆分查询以及如何检索第 2 页的下 20 个联系人和第 3 页的第 3 个 20 个联系人?

我使用的是 MS SQL Server 2012。

【问题讨论】:

    标签: sql sql-server performance stored-procedures sql-server-2012


    【解决方案1】:

    您可以将common table expressionROW_NUMBER() 函数结合使用

    ALTER PROCEDURE [dbo].[GetAllContacts] 
        @searchVal VARCHAR(500), 
        @page INT = NULL, 
        @perPage INT = NULL
    AS
        DECLARE @Start INT, @End INT
    
        SET @page = ISNULL(@page, 1)
        SET @perPage = ISNULL(@perPage, 10)
    
        SET @start = CASE WHEN @page = 1 THEN 0 ELSE (@page - 1) * @perPage END + 1
        SET @end =  CASE WHEN @page = 1 THEN @perPage ELSE (@page * @perPage) END
    
        ;WITH [Contacts] AS (
        SELECT  [Id]
                , [FirstName] , [LastName]
                , [Address] , [Tel_no]
                , ROW_NUMBER( ) OVER (ORDER BY LastName) AS [Index]
        FROM    [tblContact]
        WHERE ([FirstName] LIKE ('%'+ @searchVal +'%') 
            OR [LastName]  LIKE ('%'+ @searchVal +'%'))
        ), [Counter] AS (SELECT COUNT(*) AS [Count] FROM [Contacts])
        SELECT  [Id]
            , [FirstName] , [LastName]
            , [Address] , [Tel_no]
            , @page AS CurrentPage
            , @perPage AS PageSize
            ,CEILING(CAST([Counter].[Count] AS DECIMAL(18,2))/@perPage) AS TotalPages
        FROM Contacts, [Counter]
        WHERE [Index] >= @start AND [Index] <= @end
    

    然后您可以通过传入搜索词、要显示的页面以及每页上所需的条目数来调用它

    EXEC [dbo].[GetAllContacts] 'Smith', 3, 20
    

    这将返回名字或姓氏中包含“Smith”一词的联系人的第 3 页

    例如:http://sqlfiddle.com/#!6/bb8ae/2

    【讨论】:

      【解决方案2】:

      我找到了(通过使用 orderedIndex);

      ALTER PROCEDURE [dbo].[GetAllContacts] (@searchVal  varchar(500) 
                                           ,  @CurrentPage int
                                           ,  @PageSize   int)
      AS
      BEGIN
      
      DECLARE @RESULTS TABLE (
              orderedIndex                    int IDENTITY(1,1) PRIMARY KEY
          ,   Id                              bigint        NOT NULL
          ,   FirstName                       nvarchar(30)  NULL
          ,   LastName                        nvarchar(30)  NULL
          ,   Address                         nvarchar(130)  NULL
          ,   Tel_no                          nvarchar(15)  NULL )
      
      SET @CurrentPage = ISNULL(@CurrentPage, 1)
      SET @PageSize = ISNULL(@PageSize, 10)
      
      
      INSERT INTO @RESULTS (Id, FirstName, LastName, Address,Tel_no)    
      Select  distinct(Id) as Id
        , FirstName
        , LastName
        , Address
        , Tel_no
      from    tblContact     
      Where (FirstName like ('%'+ @searchVal +'%') OR LastName  like ('%'+ @searchVal +'%'))
      Order by LastName
      
      -- Get result on separate pages
      SELECT     Id
              ,  FirstName
              ,  LastName                 
              ,  Address
              ,  Tel_no
              , (SELECT COUNT(*) FROM @RESULTS) AS NbResults
              , @CurrentPage AS CurrentPage
              , @PageSize AS PageSize
              , FLOOR(CEILING(Cast((SELECT COUNT(*) FROM @RESULTS) as decimal(18,2))/ @PageSize)) as TotalPages 
      
      FROM @RESULTS 
      WHERE orderedIndex BETWEEN 1 + ((@CurrentPage - 1) * @PageSize) AND (@CurrentPage) * @PageSize
      
      END
      

      【讨论】:

      • 这效率不高。即使您只需要一页,您也正在实现整个结果集。
      【解决方案3】:

      试试这个 -

      CREATE PROCEDURE [dbo].[GetAllContacts] 
      (
            @searchVal VARCHAR(500)
          , @from INT
          , @row_count INT = 20
      )
      AS
      BEGIN
      
          SELECT DISTINCT (Id) AS Id
                      ,   FirstName
                      ,   LastName
                      ,   address
                      ,   Tel_no
          FROM tblContact
          WHERE FirstName LIKE '%' + @searchVal + '%'
              OR LastName LIKE '%' + @searchVal + '%'
          ORDER BY LastName
              OFFSET @from ROWS
              FETCH NEXT @row_count ROWS ONLY;
      
      END
      

      例子-

      EXEC GetAllContacts @searchVal = ''
          ,   @from = 0
          ,   @row_count = 20
      
      EXEC GetAllContacts @searchVal = ''
          ,   @from = 20
          ,   @row_count = 20
      
      EXEC GetAllContacts @searchVal = ''
          ,   @from = 40
          ,   @row_count = 20
      

      【讨论】:

        猜你喜欢
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-22
        • 1970-01-01
        相关资源
        最近更新 更多