Question

I am using pagination with CSqlDataProvider. Result is shown properly for the first 20 or first page of the pagination. When I see the Log message on the web page the query it uses is actually selecting top 20 rows for all the pages and that's the problem. I have no idea how to correct it.

My controller has code:

public function actionLink()
 {
      $sql = "SELECT Ordernumber, Order_Date
                FROM [Orders]
                WHERE CAST(Order_Date As Date) BETWEEN '01-01-2014' AND '31-01-2014'";

      $count = Yii::app()->db->createCommand('SELECT COUNT(*) FROM (' . $sql . ') as count_alias')->queryScalar();
      $dataProvider = new CSqlDataProvider($sql, array('keyField' => 'Order_Date',
           'totalItemCount' => $count,
           'pagination' => array(
           'pageSize' => 20,),));

      $this->render('link',  array('dataProvider' => $dataProvider));
    }}      

And now the query which it uses for count is correct(Log Message):

Querying SQL:

SELECT COUNT(*) FROM (SELECT Ordernumber ,Order_Date
FROM [Orders]
WHERE CAST(Order_Date As Date) BETWEEN '01-01-2014' AND '31-01-2014') as count_alias

The query it uses for page 2 is(Log Message):

 SELECT * FROM (SELECT TOP 20 * FROM (SELECT TOP 40 Ordernumber,Order_Date
 FROM [Orders]
 WHERE CAST(Order_Date As Date) 
 BETWEEN '01-01-2014' AND '31-01-2014') as [__inner__]) as [__outer__]

The above query actually will give result as first 20 rows. Its the same problem with every page. It gives every result as the same first 20 rows. So Page 3 becomes(Log Message):

 SELECT * FROM (SELECT TOP 20 * FROM (SELECT TOP 60 Ordernumber,Order_Date
 FROM [Orders]
 WHERE CAST(Order_Date As Date) 
 BETWEEN '01-01-2014' AND '31-01-2014') 
 as [__inner__] ) as [__outer__]

The only problem I can see is the query it is using to retrieve the data for page 2,3.. and so on. For every page it returns the same data because every time it is selecting TOP 20 rows. I don't understand reason for this behavior. How does the query actually looks like when you use SQL SERVER as DB and CSqlDataProvider as data provider during pagination?

Was it helpful?

Solution

I found the solution. I had to change the rewriteLimitOffsetSql function in CMssqlCommandBuilder to:

return $sql." OFFSET ".$offset." ROWS FETCH NEXT ".$limit." ROWS ONLY";

Just this one line in function and remove the rest of the code. Good that SQL SERVER started support for OFFSET and FETCH.

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