Sorting in yii Cdbcriteria with sum(amount) - php

I need to show highest amount on the top in yii Cgridview.
I have two models: members and billing,
member_id is foregion key in billing model.
My Model Function:
public function getImportantMembers(){
$criteria = new CDbCriteria;
$criteria->select ='t.*,b.billing_id,b.amount,b.billing_date,b.member_id,b.billing_status , sum(b.amount) AS totalamount';
$criteria->join = 'JOIN billing AS b ON b.member_id = t.id ';
$criteria->addCondition("b.billing_date > DATE_SUB(NOW(),INTERVAL 2 MONTH) AND b.billing_status='c' AND b.amount > 150 ");
$criteria->group = 't.id';
$criteria->order = " totalamount DESC";
return new CActiveDataProvider(get_class($this),array(
'pagination'=>array(
'pageSize'=> Yii::app()->user->getState('pageSize',Yii::app()->params['defaultPageSize']),),
'criteria'=>$criteria,
));
}
but this function not showing correctly highest amount at the top or amount DESC
How I can fix this?

Define relations in your models and use them in your criteria. Then pass a CSort object to the DataProvider like below. You can define custom sort parameters as long as you define them in your model.
return new CActiveDataProvider( 'Model', array(
'criteria'=>$criteria,
'sort'=>array(
'attributes'=>array(
...........
...........
'*',
),
),
));
For details this link will help.
http://www.yiiframework.com/wiki/281/searching-and-sorting-by-related-model-in-cgridview/
If that link doesn't help post your model codes for both the tables and I'll try to provide some example code.

Related

Yii 1 - Ordering by relation field not working

I know its a common question but I get a specific error about a not joined table.
My main Model (Group) has this relation (1:1):
return array(
'groupType'=>array(self::BELONGS_TO, 'GroupType', 'groupTypeId','order'=>'name ASC');
As you can see, I've tried to put an order attributes thats is not working.
As you can immagine, my other module, GroupType, has an attribute called 'name'.
In the grid view, the relation model is printed well simply using the name of relation:
array(
'name'=>'groupType',
'value'=>'$data->groupType->name'
),
Autoload is working fine in GridView.
Unfortunally the column is not sortable. So I put a CSort parameter to DataProvider provided in the Search Method as below:
$sort = new CSort();
$sort->defaultOrder = 'id asc';
$sort->attributes = array(
'groupType'=>array(
'asc'=>'groupType.name asc',
'desc'=>'groupType.name desc'
),
'description'=>array(
'asc'=>'t.description asc',
'desc'=>'t.description desc'
),
'name'=>array(
'asc'=>'t.name asc',
'desc'=>'t.name desc'
),
'*');
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort
));
Ordering by description and name (attribute of Group) works fine. When I tried to order by groupType, i get this simply error:
SQL: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'groupType.id' in 'order clause'. The SQL statement executed was: SELECT * FROM `cprol_groups` `t` ORDER BY groupType.idname asc LIMIT 20
As you can see, framework is not joining my related table. And in this case, what Alias I have to use due to same-property name?
Thanks you for any advice!
I've resolved forcing the join.
In the criteria, I have to force join:
$criteria->join = 'join '.GroupType::model()->tableName().' gt on gt.id = t.groupTypeId';
or using the ->with statement:
$criteria->with = 'groupType';
removing the default order in relation and adding an alias:
return array('groupType'=>array(self::BELONGS_TO, 'GroupType', 'groupTypeId','alias'=>'gt'));
so you can order by relation field:
$sort = new CSort();
$sort->defaultOrder = 'gt.name asc';
$sort->attributes = array(
'groupTypeId'=>array(
'asc'=>'gt.name asc',
'desc'=>'gt.name desc'
),

Yii: computing aggregate by date

I have a simple model in Yii 1.1:
Expense
amount: int
date: string
How do I compute an aggregate by date using build-in Yii capabilities?
In other words I would like to get a result of the following query using Yii:
SELECT
date, SUM(amount) AS dateAmount
FROM
tbl_expense
GROUP BY
date
ORDER BY
date DESC
I have explored 2 ways for executing query,
First:
$list= Yii::app()->db->createCommand('SELECT date, SUM(amount) AS dateAmount
FROM tbl_expense
GROUP BY date
ORDER BY date DESC')->queryAll();
var_dump($list->getData());
Second:
(Normally used to provide dataprovider to Gridview and Listview)
$select = "SELECT date, SUM(amount) AS dateAmount
FROM tbl_expense
GROUP BY date
ORDER BY date DESC";
$dataProvider=new CSqlDataProvider($select,
array(
'pagination'=>false,
'params'=>$sqlParam
)
);
var_dump($dataProvider->getData());
You could use criteria
$criteria = new CDbCriteria();
$criteria->select = 'date, SUM(amount) dateAmount';
$criteria->group = 'date';
$model=Expense::model()->find($criteria);
You can use criteria
$criteria = new CDbCriteria();
$criteria->select = 'date, SUM(amount) dateAmount';
$criteria->group = 'date';
$model=Expense::model()->find($criteria);
AND
add property dateAmount to the model class.
class SomeClass extends CActiveRecord {
public $dateAmount;
...
}

PHP Yii: how to row numbering CGridView if using sqlite database

I want to show a filter-able and sort-able column of row number in CGridView, but what i have got is only an empty sort-able (clickable header) and filter-able (it has filtering text box up there) column.
In model (ActiveRecord) class i have added a new public attribute:
public $number;
in the rules() function i have added:
public function rules()
{
return array(
...
...
array('
...
...
number,
',
'safe',
'on'=>'search'
),
);
}
on the search() function, i have also add:
public function search()
{
$criteria=new CDbCriteria;
...
...
$number_select = '(
select count(*)
from tbl_mytable as k
where k.id <= t.id
)';
$criteria->select = array(
$number_select . ' as number',
't.*',
);
...
...
$criteria->compare($number_select, $this->number,true);
$sort = new CSort;
$sort->attributes = array(
'*',
...
...
'number'=>array(),
);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort,
));
}
I've successfully using this kind of method to add other columns.
With the lack of skill and knowledge of sqlite query, i am suspecting the cause of this problem is the query in the $criteria->select.
I hope someone would help me for solving this.
Try adding the property to CActiveRecord.attributeNames:
public function attributeNames()
{
return array_merge(parent::attributeNames(), array('number'));
}
after editing my question, i edited my code a fad that miraculously turn out to be the answer.
Just remove the table alias from the select statement
Original (not working) code:
$number_select = '(
select count(*)
from tbl_mytable as k
where k.id <= t.id
)';
The new (working) code after removing table alias:
$number_select = '(
select count(*)
from tbl_mytable
where tbl_mytable.id <= t.id
)';
While my question is about yii with sqlite database, but since this is quite standard query, i think this solution will also works for yii with mysql database

Doing Join query using CDBCriteria

I am trying to do a Join query using CDBCriteria in Yii framework. The issue is the join query works successfully but it does not display the columns from other tables.
I am doing in the following way
$criteria = new CDbCriteria;
$criteria->order = 't.id desc';
$criteria->select = '*';
$criteria->join = ' INNER JOIN table2 INNER JOIN table3 INNER JOIN table4';
When i run this, I can see only the mail table1 columns displayed. Other columns are not shown.
In my model class, I have the relation has
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'user' => array(self::BELONGS_TO, 'DmPhoneUser', 'user_id'),
'command' => array(self::BELONGS_TO, 'DmOtaCommand', 'command_id'),
'partner' => array(self::BELONGS_TO, 'DmPartner', 'partner_id'),
);
}
********************************************************
public function actionGetHistory($start, $per_page)
{
$partner_id = '10';
$criteria = new CDbCriteria;
$criteria->order = 't.history_id desc';
$criteria->select = 't.*, table2.*';
$criteria->join = ' INNER JOIN table2 ON t.command_id = table2.command_id';
$result = Table_1_class::model()->with('command')->findAll();
$history_data = CJSON::encode($result);
echo $history_data;
}
here command_id is common in table1 and table2.
This is how I am using the criteria code.
As I said, Yii's Active Record implementation will only use columns which are defined in the table itself or the tables you are linking to through with, not arbitrary columns you return in the resultset.
Solution 1: Define a relation to table2, add that relation to with, and get rid of join. Then you'll probably need to convert each returned object to an array - CJSON::encode will not handle a model with relations well.
Solution 2: Use Yii::app()->db->createCommand("SQL query")->queryAll(); instead of Active Record. This will produce an array of arrays, which CJSON::encode will have no problem with.

How do I specify the tablename in a filter in Yii?

There's two tables, attendee, and group. both have a gender field. Each attendee is assigned to 1 group. I've got my CGridView successfully showing the number of attendees, but when I added code to filter on gender, I get the following error. To calculate the number of attendees in a group, I'm manually performing a join; but the join makes the field 'gender' ambiguous. Is there any way to specify in the filter that it should use the 't' or base table?
When I load the view it operates correctly; when I click to sort on gender, it gives me this message:
Error Message
> Error 500: <h1>CDbException</h1>
> <p>CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'gender'
> in where clause is ambiguous. The SQL statement executed was: SELECT
> COUNT(*) FROM (SELECT t.*, IFNULL( count(tbl_attendee.id), 0) as
> attendeeCount FROM `tbl_group` `t` LEFT JOIN tbl_attendee ON
> tbl_attendee.group_id = t.id WHERE gender LIKE :ycp0 GROUP BY t.id) sq
> (/Applications/MAMP/htdocs/yiiroot/framework/db/CDbCommand.php:516)</p><pre>#0
> /Applications/MAMP/htdocs/yiiroot/framework/db/CDbCommand.php(411):
> CDbCommand->queryInternal('fetchColumn', 0, Array)
Model Code
$criteria=new CDbCriteria;
$criteria->compare('name',$this->name,true);
$criteria->compare('gender',$this->gender,true);
$criteria->compare('agegroup',$this->agegroup,true);
$criteria->select = 't.*, IFNULL( count(tbl_attendee.id), 0) as attendeeCount';
$criteria->join = 'LEFT JOIN tbl_attendee ON tbl_attendee.group_id = t.id';
$criteria->group = 't.id';
$sort = new CSort();
$sort->attributes = array(
'attendeeCount'=>array(
'asc'=>'attendeeCount ASC',
'desc'=>'attendeeCount DESC',
),
'*', // add all of the other columns as sortable
);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort,
));
View Code
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'group-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'name',
array(
'name'=>'gender',
'value'=>'Group::$genderLabels[$data->gender]',
'filter'=>Group::$genderLabels, // <-- This is the filter that breaks.
// $genderLabels = array('Female','Male);
),
Ah! I got it.
Changed this line in the model code:
$criteria->compare('gender',$this->gender,true);
to
$criteria->compare('t.gender',$this->gender,true);
Found the answer here.

Categories