I have the following line of code that does a simple query
if ($this->fulfilled)
$criteria->addCondition('fulfilled ' . (($this->fulfilled == 1) ? "IS NOT NULL" : "IS NULL"));
How can modify this to do a query that contains an OR command to basically run this query using the framework rather than raw SQL
if ($this->fulfilled)
AND (fulfilled is null OR fulfilled = 0)
Try something like that
$criteriaOr = new CDbCriteria();
$criteriaOr->addCondition('fulfilled IS NULL', 'OR');
$criteriaOr->addCondition('fulfilled = 0', 'OR');
Then if($this->fulfielled) {$criteria->mergeWith($criteriaOr);}
Related
I have a user table with [FirstName] and [LastName] columns.
I'm trying to build a search function that returns users that meet one of the criteria below:
FirstName == myPattern, or
LastName == myPattern, or
FirstName LastName == myPattern
For example, if I have the following users in my database:
Jack One
Jack Two
Jack Three
I'd like the function to return all of them when the input is Jack, but only return Jack One when the input is Jack One
I currently have the following code:
var users = context.User.Where(x => x.FirstName == pattern
|| x.LastName == pattern
|| x.FirstName + " " + x.LastName == pattern)
But this does not work as the it gets translated to the following query in MySQL
...WHERE (`p`.`firstName` = 'Jack One') OR (`p`.`lastName` = 'Jack One')) OR (((`p`.`firstName` + ' ') + `p`.`lastName`) = 'Jack One')
It does not work because I believe we need to use CONCAT(firstName, ' ', lastName) if I want to concat multiple strings in MySQL.
I tried using the following .NET functions but they cannot be translated to sql (The LINQ expression ... could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync())
string.Join(' ', firstName, lastName)
string.Concat(firstName, " ", lastName)
How can I achieve this in .NET CORE 3.1 without pulling all data into memory and evaluating it in client?
Thanks
This looks like an case of Linq translating the query in a manner you aren't predicting.
Going from memory and no IDE on hand to check it, but give this a shot. If you split the full name on the space first, you can use the values in your query.
// returns an array based on the patter, if it can be split
var names = pattern.Split(" ");
// then use the array elements in the query
var users = context.User.Where(x => x.FirstName == pattern
|| x.LastName == pattern
|| (x.FirstName == names[0] && x.LastName == names[1]));
The last OR condition of the query should then evaulate the 2 new elements in the names array, that was created off the pattern
It seems a bug of MySql.Data.EntityFrameworkCore.
I use Pomelo.EntityFrameworkCore.MySql instead to solve the problem.
I am using net core 2.2 with Pomelo EntityFramework with MySql database.
The following code:
return context.SomeTable
.OrderByDescending(item => item.ExpiredTime)
.Where(item => item.FinishedTime.HasValue
&& item.ExpiredTime.HasValue
&& item.ExpiredTime.Value < DateTime.UtcNow
&& item.IsArchive.GetValueOrDefault(false) == false/* is null or false*/)
.Take(500)
.Select(i=>new ItemWrapper(i))
.ToArray();
Returns the following MySql:
SELECT `item`.`Id`, `item`.`ExpiredTime`, `item`.`FinishedTime`,
`item`.`IsArchive`
FROM `SomeTable` AS `item`
WHERE (`item`.`FinishedTime` IS NOT NULL AND `item`.`ExpiredTime` IS NOT
NULL) AND (`item`.`ExpiredTime` < UTC_TIMESTAMP())
ORDER BY `item`.`ExpiredTime` DESC
It seems like the Take(500) is not being reflected in the query.
I expect to see limit = 500 in the sql query.
Edit 1:
I am using Select(i=>new ItemWrapper(i) to create a new class for the result object, it seems to be the root of the issue.
What am i doing wrong?
This happens because you are calling item.IsArchive.GetValueOrDefault(false) == false in Where clause. EF.Core cannot translate this method to SQL so it materializes all the items first and then tries to apply the rest to the data retrieved from SQL server. Try to remove this condition or rewrite it. BTW, usually EF.Core shows warnings for these kind of issues in the log.
I've have the weirdest issue while trying to test something in my cakePHP 2.0 app. I have a function inside a model that queries the database to check if the app has already sent a notification in the last 25 days:
public function checkIfNotified($userId){
$query = 'SELECT count(`user_id`) AS notify '.
'FROM `churn_stats` '.
'WHERE `user_id` = '. $userId.' '.
'AND `notified` = 1 '.
'AND TIME_TO_SEC(TIMEDIFF(NOW(),`created`)) <= 2160000 ';
$this->log($query);
$result = $this->query($query);
return $result;
}
I'm doing some Unit tests to check if the method works, so I'm creating a record and trying to test it return return true like so:
$data['notified'] = 1;
$data['user_id'] = $userId;
$this->ChurnStats->create();
$this->ChurnStats->save($data);
$notified = $this->ChurnStats->checkIfNotified($userId);
print_r($notified);
After the result is (which is the wrong result since I've already inserted a row!):
Array
(
[0] => Array
(
[0] => Array
(
[notify] => 0
)
)
)
However I run the exact query generated by the code in the DB and the result is:
I've already lost a lot of time and I don't have any idea what's wrong :(.
After testing and checking everything it was another test function that somehow was changing the DB or the query of the next test, however the weird part was that the other test called the same query but didn't have any insert, update or delete that could modify the results or enviroment of the next test.
After checking everything it all reduced to something: Query Cache, by default CakePHP caches all the $this->query("..."); calls so the fix was quite easy: Deactivate it!
$result = $this->query($query, false);
In Rails 3.0.9 (Ruby 1.9.2, MySQL) I have a method that is supposed to find users using two fields, type(string) and flag(boolean). The string part of the query works fine, but not the boolean part.
here's the code:
def find_users(type)
#private_users = User.where('type =? and flag != ?', org_type, true)
end
to try to figure out what's going on, put this code:
#users.each do |f|
puts "oh helllllllllllllllllllllllllllo #{f.user_name}"
puts "oh helllllllllllllllllllllllllllo #{f.flag}"
puts "oh helllllllllllllllllllllllllllo #{f.type}"
end
The flag field is blank/null for most of these and those are the ones I'm trying to pick up.
If I change the expression to ('type =? and flag = ?', type, true), it correctly finds the ones where 1 is the value of the flag.
I've tried these things to no avail:
User.where('type =? and flag = ?', org_type, false)
User.where('type =? and flag = ?', org_type, "")
User.where('type =? and flag = ?', org_type, nil)
This probably an easy question for someone, so I hoping some knows the answer. Thank you!
Try
User.where(:type => org_type, flag: nil)
Should result in the SQL query
SELECT "users".* FROM "users" WHERE "users"."type" = 'some_type' AND "users"."flag" IS NULL
The key being that ActiveRecord will use the IS NULL operator for your flag column.
If a nullable column is NULL, you can't use normal comparison operators. You need to use the IS NULL / IS NOT NULL operator.
You can also try the NULL-safe equals (<=>) operator (which is a new one to me too)
Is it possible to construct raw SQL queries in Django so that they accept a dynamic number of arguments? So for example say that I have the following url structure in my app:
/books/category/history/
/books/category/history/1800s/
For the first query, I'm looking for all books with the keyword 'history', and for the second, I'm looking for all books with the keyword 'history' AND the keyword '1800s'.
I currently have two separate queries for each of these:
keyword1 = 'history'
SELECT appname_book.name AS name FROM appname_book WHERE keyword=%s,[keyword1]
keyword1 = 'history'
keyword2 = '1800s'
SELECT appname_book.name AS name FROM appname_book WHERE keyword=%s AND keyword=%s,[keyword1, keyword2]
Anyone know of a cleaner and more efficient way to do this?
I'm using Django 1.3 and MySQL.
Thanks.
Why dont you use Django QuerySet, like this:
Book.objects.all().filter(keyword__in=['history','1800s']).values('name')
Another possible solution using RAW SQL, coud be:
keywords = []
SQL = 'SELECT appname_book.name AS name FROM appname_book WHERE 1=1 '
SQL += ' '.join(['AND keyword=%s' for _ in params])
Sure, you could do something like this to dynamically generate a raw SQL query
sql = 'SELECT id FROM table WHERE 1 = 1'
params = []
if 'description' in args.keys():
sql += ' AND description LIKE %s'
params.append('%'+args['description']+'%')
if 'is_active' in args.keys():
sql += ' AND is_active LIKE %s'
params.append(args['is_active'])
... you can put as many "ifs" you want to construct the query
with connections['default'].cursor() as cursor:
cursor.execute(sql, params)
This way would still be completely safe against SQL Injections vulnerability