Include all column from select to groupBy mysql - php

I have a query into which I need to add all columns from select to groupBy clause. This is just an example, I've around 20-25 columns to be selected and a long query to deal with.
Eg = SELECT contact.id as id, contact.name as name,
IF ( contact.type = 'type1', NULL, contact.organization_name),
contact.occupation as occupation, contact.gender as gender
FROM table_name
WHERE <condition>
GROUP BY contact.id.
What I have in an array is this :
$select = array(
'id' => 'contact.id as id',
'name' => 'contact.name as name',
'type' => IF ( contact.type = 'type1', NULL, contact.organization_name),
'occupation' => 'contact.occupation as occupation',
'gender' => 'contact.gender as gender',
);
$groupBy = 'GROUP BY contact.id';
Now I have to dynamically update groupBy clause to include all the columns from the $select array from php code.
I've done this :
foreach ($select as $key => $val) {
$alias = explode(' as ', $val);
if ($alias[0] != 'contact_a.id') {
$selectColAlias[] = $alias[0];
}
}
$groupBy .= ', ' . implode(', ', $selectColAlias);
This is happening correctly if type is not included in the $select array.
Is there anything which would populate my groupBy clause to include all the columns from the select clause ?
As I have ONLY_FULL_GROUP_BY mode enabled. This gives an error if the above thing is not done.

Related

how to use IN query in cakephp to find multiple values

I'm using LIKE query but when specialist_id's order change it say no records found,
if specialist_id array have [1,2,3] in it then all the users with three specialties should be in results regardless of sequence, sequence array may have [3,2,1] or [2,1,3] but the users with these three specialties should be in results, here is my code with LIKE query:
$field = $this->User->find(
'all', array(
'conditions'=>array(
'User.specialist_id LIKE' =>'%'.$value.'%',
'User.role'=>'careproviderRole',
'User.gender'=>$this->request->data['gender'])
)
);
foreach ($field as $key => $value)
{
$field[$key]['Specialist'] = $user;
}
I have also tried with FIND_IN_SET:
$field = $this->User->find(
'all', array(
'conditions' => array(
'User.role' => 'careproviderRole',
'FIND_IN_SET(\''.$this->request->data['specialist_id'].'\', User.specialist_id)')
)
);
When you use LIKE with mask '%some%', it find all results with substring 'some'.
If you need to get some specific set of ids from table (1, 2 or 3), then use sql operator IN.
Example:
SELECT `specialist_id` FROM `User` WHERE `specialist_id` IN (1,2,3);
In your code it will be:
$field = $this->User->find(
'all', array(
'conditions'=>array(
'User.specialist_id' => $arrayOfSpecialistIds,
'User.role'=>'careproviderRole',
'User.gender'=>$this->request->data['gender'])
)

How to get single element from $row[id]

I'm working on a project for PHPBB. I have a problem that I get some $row types. And they have some "id"s from MySQL, But I want theese "id"s by one by.
It's SQL query ;
$sql = $db->sql_build_query('SELECT', array(
'SELECT' => 'u.*, z.friend, z.foe, p.*',
'FROM' => array(
USERS_TABLE => 'u',
POSTS_TABLE => 'p',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(ZEBRA_TABLE => 'z'),
'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id'
)
),
'WHERE' => $db->sql_in_set('p.post_id', $post_list) . '
AND u.user_id = p.poster_id'
));
$result = $db->sql_query($sql);
And then for user_id's
$rowset[$row['post_id']] = array(
'hide_post' => ($row['foe'] && ($view != 'show' || $post_id != $row['post_id'])) ? true : false,
'user_id' => $row['user_id'],
.
.
I logged $row[user_id] for in a topic and it return ;
97777
97778
97779
97783
But I want just first id i mean -> "97777" . So how can i pass just "97777" to a variable?
Dont suggest about sql level because I can't change any SQL command.
Dont suggest about sql level because I can't change any SQL command.
This is the problem though, your PHP is clearly selecting all 9 rows;
Using WHERE user_id = '97777' you will only select the record you want.
Why can you not edit the SQL? aren't you familiar with SQL or is the code your are using your own?
Without any code it is hard to say what you want to do:
reset($row);
$first_key = key($row);
or
reset($rows);
$first_key = key($rows);
Hard to guess without seeing any code.
You can limit your records using LIMIT clause.
SELECT column_name FROM table_name LIMIT 1;
It will return the first record of that table.

How to run subqueries in cakephp

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;

PHP. How to take data from 2 mysql tables instead of 1

Learning php and I am losing my mind trying to solve this for days now. Please help.
This is a code which goes thought a table COUPON, take data with a condition met, and download it afterwards. In this table COUPON I have USER_ID as number but I want to have a user name also, which is kept in another table USER.
How can I go to another table (USER) and take names (REALNAME) by this USER_ID which is the same in both tables?
if ( $_POST ) {
$team_id = abs(intval($_POST['team_id']));
$consume = $_POST['consume'];
if (!$team_id || !$consume) die('-ERR ERR_NO_DATA');
$condition = array(
'team_id' => $team_id,
'consume' => $consume,
);
$coupons = DB::LimitQuery('coupon', array(
'condition' => $condition,
));
if (!$coupons) die('-ERR ERR_NO_DATA');
$team = Table::Fetch('team', $team_id);
$name = 'coupon_'.date('Ymd');
$kn = array(
'id' => 'ID',
'secret' => 'Password',
'date' => 'Valid',
'consume' => 'Status',
);
$consume = array(
'Y' => 'Used',
'N' => 'Unused',
);
$ecoupons = array();
foreach( $coupons AS $one ) {
$one['id'] = "#{$one['id']}";
$one['consume'] = $consume[$one['consume']];
$one['date'] = date('Y-m-d', $one['expire_time']);
$ecoupons[] = $one;
}
down_xls($ecoupons, $kn, $name);
After this, I want to try to do the same thing using only SQL queries.
You would need to JOIN the tables in the SQL query
SELECT something FROM coupons as coupons JOIN user as user ON coupons.id=user.id
You should use join when you want to retrieve details from two tables.
Join table COUPON and table USER based on user_id . This should yield results you want.

Codeigniter Active Record: is it possible to remove the brakets around the table name

I am using codeigniter to produce a left join of two tables, but need to remove the brackets that active record applies to the table name. you know SELECT blah FROM ('some table') I really need these brackets to disappear.
here is my input array:
$retrieve_arr = array(
'table' => 'entries',
'select' => array('entries.entry_id', 'entries.score', 'sc_users.name', 'clients.name'),
'joins' => array(
'clients' => 'entries.client_id = clients.client_id',
'sc_users' => 'entries.sc_user_id = sc_users.sc_user_id'
),
'joinType' => 'left',
'where' => 'null'
);
here is my model:
$retrieve = new Data();
if($get_arr['select'] != 'null')
{
$query = $retrieve->db->select($get_arr['select']);
}
foreach($get_arr['joins'] as $additional => $value)
{
$retrieve->db->join($additional, $value, $get_arr['joinType']);
}
if($get_arr['where'] != 'null')
{
foreach ($get_arr['where'] as $name => $value)
{
$retrieve->db->where($name, $value);
}
}
$query = $retrieve->db->get($get_arr['table']);
$queryData = $query->result_array();
return $queryData;
and here is what my query string:
SELECT `entries`.`entry_id`, `entries`.`score`, `sc_users`.`name`, `clients`.`name` FROM (`entries`) LEFT JOIN `sc_users` ON `entries`.`sc_user_id` = `sc_users`.`sc_user_id` LEFT JOIN `clients` ON `sc_users`.`client_id` = `clients`.`client_id`Array
I have been looking for this for a while so your help is very much appreciated.
If you are referring to the ` backticks, in the Select() portion, use a FALSE as the second parameter (refer to the Users Guide for more info)

Categories