I will not go into detail about the use of row_number for paging as there are many articles about it. Most of the articles either build dynamic queries then exec it, which I think defeats the purpose of using stored procedures and is difficult to maintain, or create two stored procedures to page and the other to get the count.
Here’s an alternative using a single query:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | set nocount on
declare @computeTotalRows bit
declare @page int
declare @pageSize int
set @computeTotalRows = 1
set @page = 1
set @pageSize = 25
with Companies as (
select
RowId = row_number() over(order by main.Name)
, main.*
from (
-- main query here, not affected by inclusion of RowId
select distinct c.*
from Company c
where IsActive = 1
) as main
)
select *
, TotalRows = case
when @computeTotalRows = 1 then (select count(*) from Companies)
else -1
end
from Companies
where RowId between (@page - 1) * @pageSize + 1 and @page * @pageSize
order by Name |
Separating the main query from the outer query allows for use of the distinct qualifier without being affected by the introduction of the RowId column. (distinct is not necessary in this trivial example) The trick to computing the total rows is reusing the table expression again: select count(*) from Companies. The query is easy to main since it is not duplicated nor dynamically built in a string and is efficient since TotalRows is only computed when the bit is set. I am making an educated guess that computing the total rows within the same query provides performance gains by reusing SQL’s buffers. (I’m not a DBA, I wear the hat.) The total rows should be computed on the first page of a fresh search.
