Каков наилучший способ разбить результаты на страницы в SQL Server - PullRequest
412 голосов
/ 21 сентября 2008

Как лучше всего (с точки зрения производительности) разбивать результаты на страницы в SQL Server 2000, 2005, 2008, 2012, если вы также хотите получить общее количество результатов (до разбивки на страницы)?

Ответы [ 17 ]

1 голос
/ 29 мая 2014

Попробуйте этот подход:

SELECT TOP @offset a.*
FROM (select top @limit b.*, COUNT(*) OVER() totalrows 
        from TABLENAME b order by id asc) a
ORDER BY id desc;
0 голосов
/ 12 февраля 2016

Для метода ROW_NUMBER, если у вас нет сортировочного столбца, вы можете использовать CURRENT_TIMESTAMP следующим образом:

SELECT TOP 20 
    col1,
    col2,
    col3,
    col4
FROM (
    SELECT 
         tbl.col1 AS col1
        ,tbl.col2 AS col2
        ,tbl.col3 AS col3
        ,tbl.col4 AS col4
        ,ROW_NUMBER() OVER (
            ORDER BY CURRENT_TIMESTAMP
            ) AS sort_row
    FROM dbo.MyTable tbl
    ) AS query
WHERE query.sort_row > 10
ORDER BY query.sort_row

Это хорошо сработало для поиска по таблицам размером до 700 000.

Извлекает записи с 11 до 30.

0 голосов
/ 11 июня 2009

Ну, я использовал следующий пример запроса в моей базе данных SQL 2000, он хорошо работает и для SQL 2005. Мощность, которую он дает, динамически упорядочена с использованием нескольких столбцов. Я говорю вам ... это мощно :)

    ALTER PROCEDURE [dbo].[RE_ListingReports_SelectSummary] 

@CompanyID  int,
@pageNumber     int,
@pageSize   int, 
@sort       varchar(200)
AS

DECLARE @sql nvarchar(4000)
DECLARE @strPageSize nvarchar(20)
DECLARE @strSkippedRows nvarchar(20)
DECLARE @strFields nvarchar(4000)
DECLARE @strFilter nvarchar(4000)
DECLARE @sortBy nvarchar(4000)
DECLARE @strFrom nvarchar(4000)
DECLARE @strID nvarchar(100)

If(@pageNumber < 0)
  SET @pageNumber = 1
SET @strPageSize = CAST(@pageSize AS varchar(20)) 
SET @strSkippedRows = CAST(((@pageNumber - 1) * @pageSize) AS varchar(20))-- For    example if pageNumber is 5  pageSize is 10, then SkippedRows = 40.
SET @strID = 'ListingDbID'
SET @strFields = 'ListingDbID,
ListingID,  
[ExtraRoom]
'
SET @strFrom = ' vwListingSummary '

SET @strFilter = ' WHERE
        CompanyID = ' + CAST(@CompanyID As varchar(20)) 
End
SET @sortBy = ''
if(len(ltrim(rtrim(@sort))) > 0)
SET @sortBy = ' Order By ' + @sort

-- Total Rows Count

SET @sql =  'SELECT Count(' + @strID + ')  FROM ' + @strFROM + @strFilter
EXEC sp_executesql @sql

--// This technique is used in a Single Table pagination
SET @sql = 'SELECT ' + @strFields + ' FROM ' + @strFROM +
    ' WHERE ' + @strID +  ' IN ' + 
   '  (SELECT TOP ' + @strPageSize + ' ' + @strID + ' FROM ' + @strFROM + @strFilter + 
             ' AND  ' + @strID + ' NOT IN ' + '
          (SELECT TOP ' + @strSkippedRows + ' ' + @strID + ' FROM ' + @strFROM + @strFilter + @SortBy + ') ' 
   + @SortBy + ') ' + @SortBy
Print @sql 
EXEC sp_executesql @sql

Лучшая часть - sp_executesql кеширует последующие вызовы, при условии, что вы передаете те же параметры, т.е. генерируете тот же текст SQL.

0 голосов
/ 18 июня 2018
create PROCEDURE SP_Company_List (@pagesize int = -1 ,@pageindex int= 0   ) > AS BEGIN  SET NOCOUNT ON;


    select  Id , NameEn     from Company  ORDER by Id ASC  
OFFSET (@pageindex-1 )* @pagesize   ROWS FETCH NEXt @pagesize ROWS ONLY END  GO

DECLARE   @return_value int

EXEC  @return_value = [dbo].[SP_Company_List]         @pagesize = 1 ,         > @pageindex = 2

SELECT    'Return Value' = @return_value

GO
0 голосов
/ 13 марта 2014
   CREATE view vw_sppb_part_listsource as 
    select row_number() over (partition by sppb_part.init_id order by sppb_part.sppb_part_id asc ) as idx, * from (
      select 
          part.SPPB_PART_ID
          , 0 as is_rev
          , part.part_number 
          , part.init_id 
      from t_sppb_init_part part 
      left join t_sppb_init_partrev prev on ( part.SPPB_PART_ID = prev.SPPB_PART_ID )
      where prev.SPPB_PART_ID is null 
      union 
      select 
          part.SPPB_PART_ID
          , 1 as is_rev
          , prev.part_number 
          , part.init_id 
      from t_sppb_init_part part 
      inner join t_sppb_init_partrev prev on ( part.SPPB_PART_ID = prev.SPPB_PART_ID )
    ) sppb_part

перезапустит idx, когда дело доходит до другого init_id

0 голосов
/ 27 марта 2019

Этот бит дает возможность разбивать на страницы с использованием SQL Server и более новых версий MySQL и содержит общее количество строк в каждой строке. Использует ваш ключ pimary для подсчета количества уникальных строк.

WITH T AS
(  
  SELECT TABLE_ID, ROW_NUMBER() OVER (ORDER BY TABLE_ID) AS RN
  , (SELECT COUNT(TABLE_ID) FROM TABLE) AS TOTAL 
  FROM TABLE (NOLOCK)
)

SELECT T2.FIELD1, T2.FIELD2, T2.FIELD3, T.TOTAL 
FROM TABLE T2 (NOLOCK)
INNER JOIN T ON T2.TABLE_ID=T.TABLE_ID
WHERE T.RN >= 100
AND T.RN < 200
0 голосов
/ 21 сентября 2008

Вы не указали ни язык, ни драйвер, который используете. Поэтому я описываю это абстрактно.

  • Создать прокручиваемый набор результатов / набор данных. Это потребовало первичного на стол (ы)
  • прыгнуть до конца
  • запросить количество строк
  • перейти к началу страницы
  • прокрутка строк до конца страницы
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...