Is it possible to form a query where table1.first_name + " " + table1.last_name matches table2.customer_name?
IE:
customers.first_name = "John"
customers.last_name = "Doe"
orders.customer_name = "John Doe"
It seems to me this would be a common query, but just can't come up with the syntax intuitively.
Also, I am led to believe that this would not be a 'best practice' solution (using id fields would be better), but if I can't control the schema, I just want to know if something like my approach is even possible.
You are looking for concat
where concat(customers.first_name,' ',customers.last_name) = orders.customer_name
You can concatenate the values and compare the result as so:
(customers.first_name || ' ' || customers.last_name) = orders.customer_name
Brackets only for readability
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 want to use the "?" char for a search in a MySQL request in rails.
For example, classical way is:
Model.where("name = ?", '#{#search}')
My question is about long queries and multilines condition.
If I want to build a condition manually:
where = ""
where << " status = 1 "
where << " AND MATCH (name) AGAINST (? IN BOOLEAN MODE), #search " if #search
#records = Model.where(where)
Of course, it won't work.
So how to use the "?" (for security and simplicity) with a multilines conditions ?
A simple way is to do that:
where << " MATCH (name) AGAINST ('#{#search}' IN BOOLEAN MODE) "
But I will lose security (SQL injection) and can have problems with quotes if #search contains quotes.
Thanks,
You're getting a bit confused about the contents of where: you're putting variable names inside the string, which won't work: "#search" inside a string becomes literally the word "#search" and not a variable.
The best way to think of the arguments to where is as an array of objects, and you can build it like this. The first object is the query string (with ? symbols) and the other elements are the values for the ? symbols, which will be sanitized and translated by rails.
eg
User.where(["first_name = ? and last_name = ?", "John", "Smith"])
you can pass other things to where, like a hash of values, or a single string, but the array is the most flexible, especially in your case.
Bearing that in mind, you can do something like this to build a dynamically-created, complex query: i use this pattern a lot as it's very flexible and also very readable.
condition_strings = []
condition_values = []
condition_strings << "status = ?"
condition_values << 1 #or some dynamic data
condition_strings << "MATCH (name) AGAINST (? IN BOOLEAN MODE)"
condition_values << #search
conditions = [condition_strings.join(" AND ")] + condition_values
# => ["status = ? AND MATCH (name) AGAINST (? IN BOOLEAN MODE)", 1, "foo"]
#now we can use the array as an argument to `.where`:
#records = Model.where(conditions)
I have this query:
$sql = "
INSERT INTO table SET
name = '$name',
sku = '$number',
description = '$desc'
";
But the rows containing some special characters (in my case this ') are not inserted.. How I can solve?
Thanks in advance.
When you construct your query, you need to escape the data you are inserting.
You need to at least use addslashes() function in PHP, like this:
$sql = "INSERT INTO table SET name = '".addslashes($name)."', sku = '".addslashes($number)."', description = '".addslashes($desc)."'";
However more correct way is to use a different function than addslashes, which would properly handle all characters in the data, not only apostrophes.
I am using my custom 'escape' function like this:
function escape($text)
{
return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $text);
}
So using this function, you would write:
$sql = "INSERT INTO table SET name = '".escape($name)."', sku = '".escape($number)."', description = '".escape($desc)."'";
You must use parameterised queries instead of manually appending those values. Currently if name, number or description would contain any sql it would get executed.
A lot more detailed answer is in How can I prevent SQL injection in PHP?
Read about escaping characters in mysql. I think it is done with \
Not sure if this is possible in MySQL, but I have a column that has business names like:
AT&T Store
O'Reilly's Auto Parts
Burger King
which I import into Sphinx Search with a MySQL query. I have MariaDB, so there is a REGEXP_REPLACE(col, regexp, replace) function, but I'm having trouble figuring out the rest.
What I need is to repeat words with non-alphanumeric characters replaced with and without a space. So the above examples would become:
ATT AT T Store
OReillys O Reilly s Auto Parts
Burger King
Is this possible in a MySQL query? Thanks!
This can be done all at once, but maybe not by SQL primitive regex.
I don't know REGEXP_REPLACE, nor modern day SQL.
Typically its done by three regex.
Pseudo code:
$column_val = "O'Reilly's Auto Parts";
$new_column_val = Replace_Globally(
$column_val,
'\b\w+[[:punct:]](?:[[:punct:]]*\w)+\b',
function( $match ) {
$val = $match.value;
$text1 = Replace_Globally( $val, '[[:punct:]]+', "" );
$text2 = Replace_Globally( $val, '[[:punct:]]+', " " );
return $text1 + " " + $text2;
}
);
So, this might not look like something sql can do, so you might have to get creative.
REGEXP_REPLACE is in MariaDB only, MySQL doesn't have it.
select regexp_replace(regexp_replace(
"AT&T Store
O'Reilly's Auto Parts
Burger King",
'([[:alnum:]]+)[[:punct:]]+([[:alnum:]]+)[[:punct:]]+([[:alnum:]]+)',
'\\1\\2\\3 \\1 \\2 \\3'),
'([[:alnum:]]+)[[:punct:]]+([[:alnum:]]+)',
'\\1\\2 \\1 \\2')
I have an optional field in a database that I'm pulling out using a DAO Record Set. I need to check whether or not the field is set before I concatenate it with other fields. So far I have the following code snippet which I've tried with both Is and = (that's the obviously wrong syntax [[Is | =]]) to no avail. It appears that if I use = it will not correctly compare with Null and if I use Is then it complains that it's not comparing with an Object.
While Not rs.EOF
If rs.Fields("MiddleInitial") [[Is | =]] Null Then thisMiddleInitial = "" Else thisMiddleInitial = rs.Fields("MiddleInitial")
If prettyName(myLastName, myFirstName, myMiddleInitial) = prettyName(rs.Fields("LastName"), rs.Fields("FirstName"), thisMiddleInitial) Then
MsgBox "Yay!"
End If
rs.MoveNext
Wend
If there's a simpler way to do this I'm totally open to it. prettyName takes 3 Strings as parameters and initially I was just trying to pass rs.Fields("MiddleName") directly but it threw up at a Null value. I'd prefer to do something more direct like that but this is the best I could come up with.
How about:
IsNull(rs.Fields("MiddleInitial").Value)
You could also have a look at this article which has some explanation about Null values in Access VBA apps and how to handle them.
For the example you show, Nz would work:
thisMiddleInitial = Nz(rs!MiddleInitial,"")
Or simply concatenating the string with an empty string:
thisMiddleInitial = rs!MiddleInitial & ""
Your question has been answered by Remou, seems to me, but it occurs to me that you may just be trying to get proper concatenation of the name fields. In that case, you could use Mid() and Null propagation in VBA to get the result.
I don't use separate middle initial fields, so my usual name concatenation formula is:
Mid(("12" + LastName) & (", " + FirstName), 3)
The "12" string at the beginning is going to be tossed away if LastName is Not Null and ignored if it is null, because the + concatenation operator propagates Nulls.
To extend this to include middle intials would look like this:
Mid(("12" + LastName) & (", " + FirstName) & (" " + MiddleInitial), 3)
Assuming your UDF is not doing some kind of complicated cleanup of nicknames/abbreviations/etc., this could replace it entirely, seems to me.
If rst.Fields("MiddleInitial").Value = "Null" Then
This works for me. I use MS SQL Database.
I think the NoMatch option might work in this situation:
If rs.NoMatch = True Then
I prefer using the below to account for both Null and Empty string values. It's a good check to use you have forms collecting values from users.
If Trim(rs.Fields("MiddleInitial") & "") = "" then