Total RecordCount как OUTPUT постраничного набора результатов в хранимой процедуре

У меня есть вопрос о хранимых процедурах.

Я пытаюсь получить страницу набора результатов и количество записей всего набора.

Каждый из них работает сам по себе, но я не могу объединить это:

ALTER PROCEDURE dbo.pagingSCP
@PageStart INT, 
@PageSize INT, 
@RecordCount INT OUTPUT
AS
BEGIN
WITH AllRecords AS ( 
SELECT ROW_NUMBER() OVER (ORDER BY MATNR) 
AS Row, viewStyleColorInModul.*
FROM viewStyleColorInModul WHERE SPRAS = 'D'
) SELECT * FROM AllRecords WHERE Row between 
@PageStart and @PageStart + @PageSize
END

(Возвращено 50 строк) @RecordCount = 0 @RETURN_VALUE = 0 Завершено выполнение [dbo].[PagingSCP].

ALTER PROCEDURE dbo.pagingSCP
@PageStart INT, 
@PageSize INT, 
@RecordCount INT OUTPUT
AS
BEGIN
WITH AllRecords AS ( 
SELECT ROW_NUMBER() OVER (ORDER BY MATNR) 
AS Row, viewStyleColorInModul.*
FROM viewStyleColorInModul WHERE SPRAS = 'D'
) SELECT @RecordCount = Count(*) From AllRecords
END

Строки не затронуты. (0 строк возвращено) @RecordCount = 43770 @RETURN_VALUE = 0 Завершено выполнение [dbo].[PagingSCP].

Возможно ли каким-то образом получить 50 строк и общее количество записей в одном запросе?

Заранее спасибо.

2 ответа

Решение
ALTER PROCEDURE dbo.pagingSCP
@PageStart INT, 
@PageSize INT, 
@RecordCount INT OUTPUT
AS
BEGIN
  -- get record count
  WITH AllRecords AS ( 
    SELECT viewStyleColorInModul.*
  FROM viewStyleColorInModul WHERE SPRAS = 'D'
  ) SELECT @RecordCount = Count(*) From AllRecords;

  -- now get the records
  WITH AllRecords AS ( 
   SELECT ROW_NUMBER() OVER (ORDER BY MATNR) 
   AS Row, viewStyleColorInModul.*
   FROM viewStyleColorInModul WHERE SPRAS = 'D'
  ) SELECT * FROM AllRecords 
  WHERE Row between @PageStart and @PageStart + @PageSize;
END

У вас есть два разных запроса, поэтому вы запускаете два разных SELECT и позволяете оптимизатору SQL оптимизировать каждый в отдельности. Даже если попытка получить оба запроса в одном SELECT возможна, это крайне контрпродуктивно и неоптимально.

Как примечание, в клиентском коде любой выходной параметр доступен только после повторения всех возвращаемых результатов.

Вот смелость процесса подкачки, который мы использовали все время. Он работает, сначала выгружая все соответствующие записи во временную таблицу (WHERE SPRAS = 'D').

Затем он выбирает из временной таблицы только записи со страницы X из Y. Он также включает в себя общее количество записей исходного выбора (WHERE SPRAS = 'D').

ALTER PROCEDURE [dbo].[spSelectTempUsers] 

@Page       int = 0,
@NumPerPage int = 1

AS

SET NOCOUNT ON

CREATE TABLE #TempData 
(
[RowId]     [int] identity(1,1) ,
[UserId]    [int]               ,
[FirstName] [varchar](50)       ,
[LastName]  [varchar](50)       ,
[Email]     [varchar](255)      ,
[SPRAS]     [varchar](36)
)

INSERT INTO #TempData 
(
[UserId]    ,
[FirstName] ,
[LastName]  ,
[Email]     ,
[SPRAS]      
)

SELECT
[UserId]    ,
[FirstName] ,
[LastName]  ,
[Email]     ,
[SPRAS]      

FROM viewStyleColorInModul
WHERE [SPRAS] = 'D'


DECLARE @Count int
DECLARE @Pages int
DECLARE @i     int
DECLARE @j     int

IF @Page < 1 SET @Page = 1
SET @Count = (SELECT COUNT(RowId) FROM #TempData)
SET @Pages = @Count / @NumPerPage
IF (@Pages * @NumPerPage) < @Count SET @Pages = @Pages + 1
IF @Page > @Pages SET @Page = @Pages
SET @i = ((@Page -1) * @NumPerPage) +1
SET @j = @Page * @NumPerPage

SELECT 

ISNULL(t1.UserId,'')    as UserId,
ISNULL(t1.FirstName,'') as FirstName   ,
ISNULL(t1.LastName,'')  as LastName       ,
ISNULL(t1.Email,'')     as Email      ,
ISNULL(t1.SPRAS,'')     as SPRAS,

@Pages as Pages,
@Count as TotalRecords

FROM #TempData t1


WHERE   t1.RowId >= @i AND t1.RowId <= @j

ORDER BY t1.RowId

DROP TABLE #TempData
SET NOCOUNT OFF
Другие вопросы по тегам