I am using Ci-bonfire and I want to give alias name of table when I have join multiple table at that time it will give column ambiguous so how to give alias name of table
Here is my code example..
$select = array(
$this->table_name . '.*',
'bf_countries.name'
);
$join = array(
'bf_countries' => array(
'condition' => 'bf_countries.country_id = ' . $this->table_name . '.country_id',
'type' => 'left'
)
);
$order = array(
"sortby"=>$this->table_name.".".$this->key,
"order"=>"DESC"
);
$config = array(
"req_data" => $req_data,
"select"=>$select,
"join"=>$join,
"order"=>$order
);
$this->grid->initialize($config);
return $this->grid->get_result();
Suppose I want to give alias name of bf_countries table so what to do for that..?
Related
Cakephp 2.6
I have a Model, Temps, which has many tickets. In the index view of Temps I want to return for each record, the ticket with the date closest to the current date.
In mySQL it can be done as
'SELECT expiry_date FROM uploads WHERE expiry_date > CURDATE() ORDER BY expiry_date ASC LIMIT 1'
But I don't know how to run this as a sub query. My Current query to generate my results is as follows: (bearing in mind this has been configured for datatables) Tickets is an alias for the Upload Model
public function getAjaxIndexData($data) {
$tokens = explode(" ", $data['searchString']);
$conditions = array(
$this->alias . '.deleted' => false,
'OR' => array(
'CONCAT(' . $this->alias . '.first_name," ",' . $this->alias . '.last_name) LIKE' => '%' . implode(' ', $tokens) . '%',
),
$data['columnsFilter']
);
$fields = array(
'id',
'full_name',
'pps_number',
'mobile',
'email',
'start_date',
'time_served'
);
$order = array(
$data['orderField'] => $data['order']
);
$contain = array(
'LocalOffice.name',
);
$options = array(
'conditions' => $conditions,
'fields' => $fields,
'order' => $order,
'contain' => $contain,
'limit' => $data['limit'],
'offset' => $data['start']
);
$optionsNoFields = array(
'conditions' => $conditions,
'contain' => $contain,
);
$result['draw'] = $data['draw'];
$result['recordsTotal'] = $recordTotal = $this->find('count');
$result['recordsFiltered'] = $this->find('count', $optionsNoFields);
$result['data'] = $this->find('all', $options); //standard search
$result['data'] = $this->formatTable($result['data']);
return json_encode($result);
}
Within this query I would like to add a field that shows the nearest expiry date for each Temp.
How would I construct this?
Dynamically create a virtual field:
$this->virtualFields['nearest'] = '(SELECT expiry_date FROM uploads WHERE expiry_date > CURDATE() AND uploads.owner_id = '.$this->alias.'.ticket_id ORDER BY expiry_date ASC LIMIT 1')';
Then adjust your fields array
$fields = array(
'id',
'full_name',
'pps_number',
'mobile',
'email',
'start_date',
'time_served',
'nearest'
);
Also, the query could be rewritten as ("temp" needs to be replaced with the model alias)
SELECT MIN(expiry_date)
FROM uploads
WHERE expiry_date > CURDATE()
AND uploads.owner_id = temp.ticket_id;
Which means that a potentially better performing query would be to move that subquery out of the columns of the SELECT statement to a JOIN. For example:
SELECT *
FROM temp
LEFT JOIN (SELECT MIN(expiry_date) AS expiry,owner_id
FROM uploads
WHERE expiry_date > CURDATE())
GROUP BY owner_id) AS next_dates
ON next_dates.owner_id = temp.ticket_id;
I am building an application using CakePHP and I am stuck on a problem retrieving data using a series of joins. In the simplified example below the join with the alias Delivery could have more than record and I want to bring back the record with a max value in a particular field in that table.
$inv_conditions = array( 'Invoice.invoice_date >=' => $DateFormatter->dateForDB($dateFrom),
'Invoice.invoice_date <=' => $DateFormatter->dateForDB($dateTo),
'Invoice.id >' => 385380 );
$join = array(array(
'table' => 'jobs',
'alias' => 'Jobs',
'type' => 'LEFT',
'conditions' => array('Invoice.job_id = Jobs.JOB_ID' )
),
array(
'table' => 'functional',
'alias' => 'Delivery',
'type' => 'LEFT'
'conditions'=> array('AND ' => array('Invoice.job_id = Delivery.JOB',
'Delivery.TYPE_STAGE = 1')
)
)
);
$invoices = $this->Invoice->find("all", array(
"fields" => array(
'Invoice.id',
'Invoice.job_id',
'Invoice.invoice_no',
'Invoice.consolidated_type',
'Invoice.customer_id_tbc',
'Invoice.invoice_date',
'Invoice.invoice_reference',
'Invoice.invoice_req',
'Jobs.PAYMENT_TYPE',
'Jobs.CUSTOMER',
'Jobs.MOST_RELEVANT_LINE',
'Delivery.DEPARTURE_DATE',
'Delivery.CNOR_CNEE_NAME',
'Delivery.TOWN_NAME',
),
"conditions" => $inv_conditions,
"joins" => $join
)
);
}
I can do this with SQL no problem as follows:
SELECT
jobs.JOB_ID,
jobs.CUSTOMER,
functional.JOB_LINE_ORDER,
functional.CNOR_CNEE_NAME,
functional.TOWN_NAME
FROM jobs JOIN functional ON
jobs.JOB_ID = 'M201409180267'
AND
functional.JOB = jobs.JOB_ID
AND
functional.TYPE_STAGE = 0
AND
functional.JOB_LINE_ORDER =
(SELECT MAX(JOB_LINE_ORDER) FROM functional
WHERE functional.JOB = 'M201409180267' AND functional.TYPE_STAGE = 0)
I have tried using the following to the conditions array:
'conditions' => array('AND ' =>
array( 'Invoice.job_id = Delivery.JOB',
'Delivery.TYPE_STAGE = 1'
'Delivery.JOB_LINE_ORDER = MAXIMUM(Delivery.JOB_LINE_ORDER)' )
)
This does bring back results but not the correct ones and the resulting SQL generated by Cake does have a select in the where clause. Is there a way of doing this when retrieving data in cake where the sql statement created will have a select in the where clause.
Any suggestions would be greatly appreciated.
Thanks
Bas
You need to use subquery to generate the select in the where clause. You can create a method in your model that does this and call it from your controller.
$subQuery = $db->buildStatement(
array(
'fields' => array(''),
'table' => $db->fullTableName($this),
'alias' => 'aliasName',
'limit' => null,
'offset' => null,
'joins' => array(),
'conditions' => $conditionsArray,
'order' => null,
'group' => null
),
$this
);
$subQuery = ' <<YOUR MAIN QUERY CONDITION (' . $subQuery . ') >>';
$subQueryExpression = $db->expression($subQuery);
$conditions[] = $subQueryExpression;
return $this->Model->find('list', compact('conditions'));
I joined some tables in model by CDbCriteria my code is something like this :
$crt = new CDbCriteria();
$crt->alias = 'so';
$crt->select = 'u.id, u.first_name, u.last_name';
$crt->join = " inner join " . Flow::model()->tableName() . " as fl on fl.id = so.flow_id";
$crt->join .= " inner join " . RoleUser::model()->tableName() . " as ru on ru.id = fl.receiver_role_user_id";
$crt->join .= " inner join " . User::model()->tableName() . " as u on ru.user_id= u.id";
$crt->compare('sms_outbox_group_id', $smsOutboxGroupId);
$crt->compare('fl.kind', Flow::KIND_SMS);
$crt->group = 'u.id';
$smsOutBox = new SmsOutbox();
return new CActiveDataProvider($smsOutBox, array(
'criteria' => $crt,
'sort' => array(
'defaultOrder' => 'so.id DESC',
)
));
how can I show my selected column in CGridView? is there any possible way to show first_name and last_name without defining relation in model?
I've found the solution using Sudhanshu Saxena answer. beside using aliases for first_name and last_name I've added two property to model with same names as aliases : receiverFirstName and receiverLastName. in this way my problem was solved and besides that it provide search functionality on this two property.
my final code is like this :
Model :
public $receiverFirstName;
public $receiverLastName;
creating criteria :
$crt = new CDbCriteria();
$crt->alias = 'so';
$crt->select = 'so.id,u.id as userId, u.first_name as receiverFirstName, u.last_name as receiverLastName, so.status';
$crt->join = " inner join " . Flow::model()->tableName() . " as fl on fl.id = so.flow_id";
$crt->join .= " inner join " . RoleUser::model()->tableName() . " as ru on ru.id = fl.receiver_role_user_id";
$crt->join .= " inner join " . User::model()->tableName() . " as u on ru.user_id= u.id";
$crt->compare('sms_outbox_group_id', $smsOutboxGroupId);
$crt->compare('u.first_name', $this->receiverFirstName, true);
$crt->compare('u.last_name', $this->receiverLastName, true);
$crt->compare('so.status', $this->status);
$crt->compare('fl.kind', Flow::KIND_SMS);
$crt->group = 'userId';
$crt->order = 'so.id';
return new CActiveDataProvider($this, array(
'criteria' => $crt,
));
and finally in CgridView I did this :
'columns' => array(
array(
'header' => Yii::t('app', 'Row'),
'value' => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
array(
'name' => 'receiverFirstName',
'value' => '$data->receiverFirstName',
),
array(
'name' => 'receiverLastName',
'value' => '$data->receiverLastName',
),
array(
'name' => 'status',
'value' => 'SmsOutbox::getStatusTitle($data->status)',
'filter' => CHtml::listData(SmsOutbox::getStatusList(), 'id', 'title')
),
),
Use the alias and call it in CgridView like this
$crt->select = 'u.id, u.first_name as fname, u.last_name as lastname';
In your Grid call it.
array('name'=>'name' or 'header'=>'some header','value'=>'$data->fname')
In the following cakephp mysql query, how do I find number of rows grouped each time?
$groupBy = 'PropertyViewer.ip_address';
$this->paginate = array(
"group" => array( $groupBy ),
"order" => array( "PropertyViewer.id desc" ) );
$view_info = $this->paginate( 'PropertyViewer', $conditions );
$this->set( 'view_info', $view_info );`
You can do it like in the following way, however I did not try it but it will work.
$groupBy = 'PropertyViewer.ip_address';
$this->paginate = array( "fields" => (..., 'COUNT(PropertyViewer.id) AS total_rows),
"group" => array( $groupBy ),
"order" => array( "PropertyViewer.id desc" ) );
$view_info = $this->paginate( 'PropertyViewer', $conditions );
$this->set( 'view_info', $view_info );`
Or you can also create a virtual Field in your model, if you need it to use frequently.
I have two tables, User and Company. I have joining them like this:
$table = $this->getDbTable();
$select = $table->select();
$select->setIntegrityCheck( false );
$select->from( array('User'), array( 'id' => 'id',
'name' => 'User.name',
'gender' => 'User.gender',
'Company_id' => 'User.Company_id'
));
$select->join( 'Company', 'Company.id = User.Company_id',
array( 'Company_name' => 'Company.name' ,
'Company_address' => 'Company.address'
));
$rows = $table->fetchAll( $select );
It is working and giving me accurate result. Problem is that I have to mentions column names in above codes. I want to get all columns without mentioning them in above piece of code.
For example I want something like this that get all columns(But it is not providing all column values):
$table = $this->getDbTable();
$select = $table->select();
$select->setIntegrityCheck( false );
$select->from( array('User') );
$select->join( 'Company', 'Company.id = User.Company_id' );
$rows = $table->fetchAll( $select );
Thanks
Leaving away the second parameter to the from call should work: http://framework.zend.com/manual/en/zend.db.select.html#zend.db.select.building.columns