Question

I use following query for paging in my application (MVC4, SQL Server):

string sql = "SELECT Id, Name, Date, allCount FROM (" +
             "SELECT Id, Name, Date, COUNT(Id) OVER() as allCount, " +
             "ROW_NUMBER() OVER (ORDER BY Date DESC, Id ) AS RowNum FROM Products) AS SOD " +
             "WHERE SOD.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1 AND @RowsPerPage*(@PageNumber) ORDER BY Date DESC";

This works for me, but I want to know is it a normal approach to count allCount many times? I am afraid that to count allCount many times, will affect the speed for bulk data. But, In view I need count of all products to make pagination. Is it normal code if not, how can I change it?

Was it helpful?

Solution

I would perhaps inline your Between operation parameters in your .net. You can control the calculation to run only once. I personally don't trust SQL server to decide what is "deterministic" since I have been bitten a few times. Also why do you need to return allcount in EVERY row. If you are using ADO.Net rather than an ORM, then you can control your SQL as you want.

Do

SELECT Count(*); 

SELECT id, 
       name, 
       date 
FROM   (SELECT id, 
               name, 
               date, 
               Row_number() 
                 OVER ( 
                   ORDER BY date DESC, id ) AS RowNum 
        FROM   products) AS SOD 
WHERE  SOD.rownum BETWEEN @Start AND @End 
ORDER  BY date DESC 

Although I suspect that you can just use a HAVING clause instead of your inner query with WHERE.

OTHER TIPS

Even though it might seem from the resulting data, that the COUNT(Id)-operation is performed once for every record in the dataset, the count is in fact only performed once. The query optimizer knows that the expression COUNT(Id) OVER() is independent of the current record, which allows it to only do the count once.

As such, I don't see anything wrong with your query, in terms of paging.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top