CTE, ROW_NUMBER и ROWCOUNT - PullRequest
       33

CTE, ROW_NUMBER и ROWCOUNT

11 голосов
/ 15 сентября 2011

Я пытаюсь вернуть страницу данных, а также количество строк всех данных в одной хранимой процедуре, которая выглядит следующим образом:

WITH Props AS
(
    SELECT *,
    ROW_NUMBER() OVER (ORDER BY PropertyID) AS RowNumber
    FROM Property
    WHERE PropertyType = @PropertyType AND ...
)   

SELECT * FROM Props 
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 AND (@PageNumber * @PageSize);

Я не могу вернуть количество строк (наибольшее число строк).

Я знаю, что это уже обсуждалось (я видел это: Эффективный способ получения @@ rowcount из запроса с использованием row_number ), но когда я добавляю COUNT (x) OVER (PARTITION BY 1) в производительности CTE, и запрос выше, что обычно не занимает много времени, не требует времени, чтобы выполнить. Я считаю, это потому, что счет рассчитывается для каждой строки? Кажется, я не могу повторно использовать CTE в другом запросе. Table Props имеет 100 тыс. Записей, CTE возвращает 5 тыс. Записей.

Ответы [ 3 ]

16 голосов
/ 16 сентября 2011

В T-SQL это должно быть

;WITH Props AS
(
    SELECT *,
        ROW_NUMBER() OVER (ORDER BY PropertyID) AS RowNumber
    FROM Property
    WHERE PropertyType = @PropertyType AND ...
)

, Props2 AS
(
    SELECT COUNT(*) CNT FROM Props
)

-- Now you can use even Props2.CNT
SELECT * FROM Props, Props2
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 AND (@PageNumber * @PageSize);

теперь у вас есть CNT в каждой строке ... Или вы хотели что-то другое? Вы хотели второй набор результатов только с количеством? Тогда сделай это!

-- This could be the second result-set of your query.
SELECT COUNT(*) CNT
FROM Property
WHERE PropertyType = @PropertyType AND ...

Примечание: повторно отредактировано, запрос 1, на который ссылался Дэвид, теперь был просмотрен в мусорном ведении, запрос 2 теперь является запросом 1.

1 голос
/ 22 ноября 2018

Я застрял с той же проблемой и хочу поделиться трюком, как вернуть страницу и общее количество строк .Проблема исправлена ​​временной таблицей .Вот тело хранимой процедуры:

DECLARE @personsPageTable TABLE(
  RowNumber INT, 
  PersonId INT, 
  FirstName NVARCHAR(50), 
  LastName NVARCHAR(50), 
  BirthDate DATE, 
  TotalCount INT);

        ;WITH PersonPage AS 
        (
            SELECT 
                 ROW_NUMBER() OVER(ORDER BY persons.Id) RowNumber,
                 Id,
                 FirstName,
                 LastName,
                 BirthDate
            FROM Persons
            WHERE BirthDate >= @BirthDateFrom AND BirthDate <= @BirthDateTo
        ), TotalCount AS( SELECT COUNT(*) AS [Count] FROM PersonPage)
        INSERT INTO @personsPageTable
        SELECT *, (select * from TotalCount) TotalCount FROM PersonPage
        ORDER BY PersonPage.RowNumber ASC
        OFFSET ((@pageNumber - 1) * @pageSize) ROWS
        FETCH NEXT @pageSize ROWS ONLY

        SELECT TOP 1 TotalCount FROM @personsPageTable

        SELECT 
            PersonId, 
            FirstName, 
            LastName, 
            BirthDate
        FROM @personsPageTable

Как вы можете видеть, я помещаю CTE result и total строк во временную таблицу и выбираю два запроса.Первый общий счетчик возврата и вторая страница возврата с данными.

1 голос
/ 15 сентября 2011

Вы хотите, чтобы счет для всего набора результатов был правильным?

Это работает по-быстрому?

SELECT *,(select MAX(RowNumber) from Props) as MaxRow 
FROM Props 
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 
    AND (@PageNumber * @PageSize);
...