How get list without some city in query condition. Something like that
joinWith(['address' => function($query){
$query->orWhere(['order_delivery_address_city' => 'New York']);
$query->orWhere([ 'order_delivery_address_city' => 'London']);
How set negation for this like != New York?
$query->orWhere(['NOT', ['order_delivery_address_city' => 'New York']]);
It is operator form of condition, you might Google more about it,
Instead of 'NOT' you can use operators like < > != = Etc...
Related
I'm updating a record in this way:
Yii::$app->db->createCommand()->update('table', ['config' => json_encode($array)],
'field1 = :field1', [':field1' => $field1]
)->execute();
My aim is to add an extra condition with the AND operator but I don't know how to do it.
I've followed this example: LINK
// UPDATE (table name, column values, condition)
Yii::$app->db->createCommand()->update('user', ['status' => 1], 'age > 30')->execute();
But it doesn't show a lot of possibilities.
try this way
Yii::$app->db->createCommand()
->update('table', ['config' => json_encode($array)],
'field1 = :field1 AND field2 = :field2',[':field1' => $field1,':field2' => $field2])
->execute();
Just like an array, with each condition separated by a ,.
In your case:
Yii::$app->db->createCommand()->update(
'table',
['config' => json_encode($array)],
['field1' => $field1, 'field2' => $field2]
)->execute();
Note that with this syntax you don't need to bind params, you could specify them directly inside the array of conditions as Yii2 santizes them.
I'm absolutely new to Yii2 framework. I'm trying to learn filtering, but somehow I don't understand it. I've looked in the documentation, but it didn't helped too. Could someone explain to me what this function does step by step?
public function filteringValues($query)
{
$query->andFilterWhere([
'>',
'table1.column1',
date('Y-m-d H:i:s'),
]);
}
}
just like the doc points out, andFilterWhere applies a condition if the operands are not empty
in your particular case (since date('Y-m-d H:i:s') always returns a value),
$query->andFilterWhere(['>', 'table1.column1', date('Y-m-d H:i:s')]);
will be equivalent to
$query->andWhere(['>', 'table1.column1', date('Y-m-d H:i:s')]);
which is translated to sql to a condtion like
AND (`table1`.`column1`) > '2017-08-12 06:10:32'
a propper use case for andFilterWhere is when comparing with an optional value (received as a filter param).
$query->andFilterWhere(['>', 'table1.column1', $date]);
it's purpose is to not have to check whether $date is empty or not
$query->andFilterWhere([
'table1.column1' => $param1,
'table1.column2' => $param2,
'table1.column3' => $param3,
]);
in this example, the query applies a condtion only for the params that are not empty, ignoring the extra ones
I run into this problem, time and time again. It would be nice to find out how to build queries properly so I can stop resorting to Yii::$app->db->createCommand() as a workaround.
My Yii2 query:
$users = UserSpatial::find()
->select('user_id, harvesine(y(coordinates), x(coordinates), :lat, :lon) as dist, astext(coordinates)')
->where('st_within(coordinates, envelope(linestring(point(:rlon1, :rlat1), point(:rlon2, :rlat2))))')
->orderBy('st_distance(point(:lon, :lat), coordinates)')
->params([
':lon' => $geo->lon,
':lat' => $geo->lat,
':rlon1' => $rlon1,
':rlat1' => $rlat1,
':rlon2' => $rlon2,
':rlat2' => $rlat2
])
->all();
The generated query ends up with backticks in all the wrong places and, oddly enough, not all parameters were backticked (sorry but you'll need to look closely for the misplaced backticks because I didn't know how best to highlight the incorrect placements):
SELECT \`user_id\`, harvesine(y(coordinates), x(coordinates), \`32.7699547\`, \`-116.9911288)\` AS \`dist\`, astext(coordinates)
FROM \`user_spatial\`
WHERE st_within(coordinates, envelope(linestring(point(-117.07730792871, 32.697490931884), point(-116.90494967129, 32.842418468116))))
ORDER BY st_distance(point(-116.9911288, \`32.7699547)\`, \`coordinates)\`
The query should look like the following as I did not wrap double-square-brackets around any of the fields or values:
SELECT \`user_id\`, harvesine(y(coordinates), x(coordinates), 32.7699547, -116.9911288) AS dist, astext(coordinates)
FROM \`user_spatial\`
WHERE st_within(coordinates, envelope(linestring(point(-117.07730792871, 32.697490931884), point(-116.90494967129, 32.842418468116))))
ORDER BY st_distance(point(-116.9911288, 32.7699547), coordinates)
I can live with Yii2 adding some backticks around field names and table names but why on earth is it backticking numerical values? (FYI: the $rlon and $rlat values don't seem to get backticked but I was assuming that was because they are a result of math calculations!?!?).
I've already tried forcing $geo->lon and $geo->lat to float values like so:
'lon' => (float)$geo->lon;
or
'lon' => (float)$geo->lon * 1;
but it didn't help.
Try to use array format for select and orderBy methods, like docs suggest:
Besides column names, you can also select DB expressions. You must use
the array format when selecting a DB expression that contains commas
to avoid incorrect automatic name quoting. For example,
$query->select(["CONCAT(first_name, ' ', last_name) AS full_name",
'email']);
In you case it will be like this:
$users = UserSpatial::find()
->select([
'user_id',
'harvesine(y(coordinates), x(coordinates), :lat, :lon) as dist',
'astext(coordinates)'
])
->where('st_within(coordinates, envelope(linestring(point(:rlon1, :rlat1), point(:rlon2, :rlat2))))')
->orderBy(['st_distance(point(:lon, :lat)', 'coordinates)'])
->params([
':lon' => $geo->lon,
':lat' => $geo->lat,
':rlon1' => $rlon1,
':rlat1' => $rlat1,
':rlon2' => $rlon2,
':rlat2' => $rlat2
])
->all();
Mysql codeigniter query is not working properly.
Suppose if mysql table looks like this:
user_id|user_name
1|john
2|alex
3|sam
Here user_name is unique
The following query should return false if user_name=john and user_id=1 and true if say user_name=john and user_id=2.
$this->db->get_where('user', array('user_name' => $name,'user_id !=' => $userid));
But it returns true in the case user_name=john and user_id=1.
Can anyone suggest me an alternative way of querying not equal to.
print($this->db->last_query()) gives:
SELECT * FROM (user) WHERE user_name = 'john' AND user_id != '1'
Why dont you use simple $this->db->query('your query');
Simply try this, Add the desired condition in the where function.
$this -> db -> where('invitee_phone !=', $user_phone);
You can go follwoing way too. It work for me
$total = 5;
$CI = get_instance();
$CI->load->database();
$CI->db->order_by('id','asc');
$topusers = $CI->db->get_where('users',array('user_type != 1 && `status` =' => 1),$total,0);
echo $CI ->db ->last_query();
die;
and if still not work for you can go with #rohit suggest: $this->db->query('your query');
Type 1:
Using ->where("column_name !=",$columnname) is fine for one column.
But if you want to check multi columns, you have to form an array inside where clause.
Like this
$whereArray = array(
"employee_name" => $name,
"employee_id !=" => $id,
);
$this->db->select('*')->from('employee')->where($whereArray);
Type 2:
We can just write exactly what we want inside where.
Like
$thi->db->where(("employee_id =1 AND employee name != 'Gopi') OR designation_name='leader#gopis clan'");
Type 2 is good for working with combining queries, i mean paranthesis "()"
you can follow this code:
$query = $this->db->select('*')->from('employee')->where('user_name', $name)->where('user_id !=', $userid)->get();
$last_query = $this->db->last_query();
$result = $query->result_array();
if you pass $name = 'john' and $userid = '1' then it return empty array.
The problem with using $this->db->query('your query'); is that it is not portable. One of the most important reasons to embrace the query builder methods is so that no matter what database driver you use, CodeIgniter ensures that the syntax is appropriate.
If a bit of discussion was possible, I'd probably like to hear why you need composite primary identifiers in your table and I'd like to see what your table schema looks like. However, I think the time for discussion has long passed.
Effectively, you want to return a boolean result stating the availability of the combination of the username AND the id -- if one is matched, but not both, then true (available).
To achieve this, you will want to search the table for an exact matching row with both qualifying conditions, count the rows, convert that integer to a boolean, then return the opposite value (the syntax is simpler than the explanation).
Consider this clean, direct, and portable one-liner.
return !$this->db->where(['user_name' => $name,'user_id' => $userid])->count_all_results('user');
this will return false if the count is > 0 and true if the count is 0.
I'm trying to use the "HAVING" clause in a SQL query using the CakePHP paginate() method.
After some searching around it looks like this can't be achieved through Cake's paginate()/find() methods.
The code I have looks something like this:
$this->paginate = array(
'fields' => $fields,
'conditions' => $conditions,
'recursive' => 1,
'limit' => 10,
'order' => $order,
'group' => 'Venue.id');
One of the $fields is an alias "distance". I want to add a query for when distance < 25 (e.g. HAVING distance < 25).
I have seen two workarounds so far, unfortunately neither suit my needs. The two I've seen are:
1) Adding the HAVING clause in the "group" option. e.g. 'group' => 'Venue.id HAVING distance < 25'. This doesn't seem to work when used in conjunction with pagination as it messes up the initial count query that is performed. (ie tries to SELECT distinct(Venue.id HAVING distance < 25) which is obviously invalid syntax.
2) Adding the HAVING clause after the WHERE condition (e.g. WHERE 1 = 1 HAVING field > 25) This doesn't work as it seems the HAVING clause must come after the group statement which Cake is placing after the WHERE condition in the query it generates.
Does anyone know of a way to do this with CakePHP's find() method? I don't want to use query() as that would involve a lot of rework and also mean I'd need to implement my own pagination logic!
Thanks in advance
You have to put it with the group conditions. like this
$this->find('all', array(
'conditions' => array(
'Post.length >=' => 100
),
'fields' => array(
'Author.id', 'COUNT(*) as Total'
),
'group' => array(
'Total HAVING Total > 10'
)
));
Hope it helps you
I used the following trick to add my own HAVING clause at the end of my WHERE clause. The "dbo->expression()" method is mentioned in the cake sub-query documentation.
function addHaving(array $existingConditions, $havingClause) {
$model = 'User';
$db = $this->$model->getDataSource();
// Two fun things at play here,
// 1 - mysql doesn't allow you to use aliases in WHERE clause
// 2 - Cake doesn't allow a HAVING clause separate from a GROUP BY
// This expression should go last in the WHERE clause (following the last AND)
$taut = count($existingConditions) > 0 ? '1 = 1' : '';
$having = $db->expression("$taut HAVING $havingClause");
$existingConditions[] = $having;
return $existingConditions;
}
As per the manual, CakePHP/2 supports having at last. It was added as find array parameter on version 2.10.0, released on 22nd July 2017.
From the 2.10 Migration Guide:
Model::find() now supports having and lock options that enable you to
add HAVING and FOR UPDATE locking clauses to your find operations.
Just had the same problem. I know, one is not supposed to modify the internal code but if you open the PaginatorComponent and you modify line 188:
$count = $object->find('count', array_merge($parameters, $extra));
to this:
$count = $object->find(
'count',
array_merge(array("fields" => $fields),$parameters, $extra)
);
Everything will be fixed. You will be able to add your HAVING clause to the 'group' and the COUNT(*) won't be a problem.
Or, make line:
$count = $object->paginateCount($conditions, $recursive, $extra);
to include the $fields:
$count = $object->paginateCount($fields,$conditions, $recursive, $extra);
After that, you can "override" the method on the Model and make sure to include the $fields in the find() and that's it!, =P
Here is another idea that doesn't solve the pagination issue, but it is clean since it just overrides the find command in AppModel. Just add a group and having element to your query and this will convert to a HAVING clause.
public function find($type = 'first', $query = array()) {
if (!empty($query['having']) && is_array($query['having']) && !empty($query['group'])) {
if ($type == 'all') {
if (!is_array($query['group'])) {
$query['group'] = array($query['group']);
}
$ds = $this->getDataSource();
$having = $ds->conditions($query['having'], true, false);
$query['group'][count($query['group']) - 1] .= " HAVING $having";
CakeLog::write('debug', 'Model->find: out query=' . print_r($query, true));
} else {
unset($query['having']);
}
}
return parent::find($type, $query);
}
Found it here
https://groups.google.com/forum/?fromgroups=#!topic/tickets-cakephp/EYFxihwb55I
Using 'having' in find did not work for me. Instead I put into one string with the group
" group => product_id, color_id having sum(quantity) > 2000 " and works like a charm.
Using CakePHP 2.9