I have a database like this:
first_name last_name
Susan Jones
Captain Kirk
Luke Skywalker
I'm trying to write a query like this:
var search = 'Luke Sky';
SELECT * FROM users WHERE first_name + last_name LIKE '%Luke Sky%'
But I don't think that syntax is correct.
In MySQL you combine strings with CONCAT(), not +, so it's:
SELECT * FROM users WHERE CONCAT(first_name, ' ', last_name') LIKE '%Luke Sky%'
What you ultimately want is something like:
WHERE ... LIKE ?
Then supply a placeholder value constructed in your application layer that has the requisite % values added on the start and end.
As always, remember that "first name" and "last name" are hazy concepts at best. Some cultures have family name first and others don't really have a last name at all.
You can do this in a couple of ways. Firstly you could split the search string on " " to give you separate first and last names and then you could do where first_name like '%Luke%' and last_name like '%sky%
Or you could use the concat function so something like concat(first_name, " ", last name) like '%Luke sky%
Personally I'd go for the first one because then it lets you match each name partially. I.e "lu sky" whereas the second way would require the first name matches fully.
Related
What is the best way to search a database for a phrase such as "Almond Anise Cookie" and return the result?
If I
SELECT *
FROM recipes
WHERE name LIKE '%".$query."%'
and use the phrase "Almond Cookie", nothing is returned as expected. But if I search for "Anise Cookie" the result above is returned.
I've also tried
SELECT *
FROM recipes
WHERE name LIKE '%".$query."%'
OR name LIKE '".$query."%'
OR name LIKE '%".$query."'
with the same failed result.
Using MATCH AGAINST returns everything that contains "Almond" and everything that contains "Cookie" also not a good result. Is there a happy middle in returned results?
You can try using REPLACE. Something like this should work:
SELECT *
FROM recipes
WHERE NAME LIKE REPLACE(' ".$query." ',' ','%');
Note that I purposely add spaces between .$query. to ensure that the replace operation will make your term filled with the wildcard symbol. In the example above:
If $query='almond cookies' then REPLACE(' ".$query." ',' ','%') will become %almond%cookies%.
You can test the fiddle here : https://www.db-fiddle.com/f/kMzp99S8ENbTkYcW5FVdYN/0
I have a huge document with names and surnames, it currently looks like this:
"name1 surname1", "name2 surname2", "name3 surname3", "name4 surname4"....
In database in users table there are columns name surname email.
What I need now is to find emails of the people from the list.
I cannot separate names and surnames since there are dozens of them.
What is the best way to find them? I guess %like% won't be working here. Please help me on this.
Note: What is difficult, some names and surnames are made of 3-4 words. This is not always only name and surname as 2 words.
DECLARE #mytxtvar TEXT;
SET #mytxtvar = LOAD_FILE('D:\\test.txt');
SELECT #mytxtvar;
SELECT email FROM user WHERE concat(name,' ',surname ) in #mytxtvar
I don't get your problem.. isn't a simple query like this one enough?
select email
from user
where
(name = 'name1' and username = 'surname1') or
(name = 'name2' and username = 'surname2') or
...
You just need to split your initial list with some language that you like or even a simple text editor and then execute the query
You can split each person on name and surname by using any language like JAVA,
Then make a batch query job for all names using loop and save the result wherever you want.
The query will be like this::
select email from user where name ='name1' and username ='surname1'
I've been trying (without success) to construct a MYSQL query which will select a group of records with a "title" field starting with a single alphabetical character but ignoring the first word if it's "The", "An" or "A". I've found plenty of examples that do this for the ORDER BY part of the query, but it's the initial WHERE part that I need to do it for, as the order is irrelevant if the correct records haven't been found. Using
WHERE title LIKE "R%"
will just give me titles that have this as the very first letter (e.g. "Robin Hood") but won't match "The Red House". I think I need some kind of REGEX, but I can't seem to get it to work.
So for example, given the following movie titles,
Road House
The Return of the King
Mamma Mia
Argo
Titanic
A River Runs Through it
Selecting movie titles that start with "R" would return the following:
The Return of the King
A River Runs Through it
Roadhouse
(other fields omitted)
The easiest way is to programmatically expand the query to something like
SELECT
...
WHERE
title LIKE 'R%'
OR title LIKE 'The R%'
OR title LIKE 'A R%'
OR title LIKE 'An R%'
...
This should perform better than a REGEX, as it will be able to use an index, which a REGEX never will.
BTW: The canonical way to do this, is to store the article in a seperate field.
This regex should suit your needs:
WHERE title REGEXP '^(The |An? )?R.*$'
But as #EugenRieck noticed, since you probably use an index on the title column, you should better use the WHERE... OR... clauses.
To add to the above suggestions (both of which I agree with), for the sort you would probably need to use a CASE to dervive a field for the ORDER BY clause.
SELECT somefield,
CASE
WHEN title LIKE 'R%' THEN title
WHEN title LIKE 'The R%' THEN SUBSTRING(title FROM 5)
WHEN title LIKE 'A R%' THEN SUBSTRING(title FROM 3)
WHEN title LIKE 'An R%' THEN SUBSTRING(title FROM 4)
ELSE title
END AS SortTitle
FROM sometable
ORDER BY SortTitle
My user table has a column "name" which contains information like this:
Joe Lee
Angela White
I want to search for either first name or last name efficiently. First name is easy, I can do
SELECT * FROM user WHERE name LIKE "ABC%"
But for last name, if I do
SELECT * FROM user WHERE name LIKE "%ABC"
That would be extremely slow.
So I am thinking about counting the characters of the input, for example, "ABC" has 3 characters, and if I can search only the last three characters in name column, that would be great. So I want something like
SELECT * FROM user WHERE substring(name, end-3, end) LIKE "ABC%"
Is there anything in MySQL that can do this?
Thanks so much!
PS. I cannot do fulltext because our search engine doesn't support that.
The reason that
WHERE name LIKE '%ith'
is a slow way to look for 'John Smith' by last name is the same reason that
WHERE Right(name, InStr(name, ' ' )) LIKE 'smi%'
or any other expression on the column is slow. It defeats the use of the index for quick lookup and leaves the MySQL server doing a full table scan or full index scan.
If you were using Oracle (that is, if you worked for a formerly wealthy employer) you could use function indexes. As it is you have to add some extra columns or some other helping data to accelerate your search.
Your smartest move is to split your first and last names into separate columns. Several other people have pointed out good reasons for doing that.
If you can't do that you could try creating an extra column which contains the name string reversed, and create an index on that column. That column will have, for example, 'John Smith' stored as 'htimS nhoJ'. Then you can search as follows.
WHERE nameReversed LIKE CONCAT(REVERSE('ith'),'%')
This search will use the index and be decently fast. I've had good success with it.
You're close. In MySQL you should be able to use InStr(str, substr) and Right(str, index) to do the following:
SELECT * FROM user WHERE Right(name, InStr(name, " ")) LIKE "ABC%"
InStr(name, " ") returns the index of the Space character (you may have to play with the " " syntax). This index is then used in the Right() function to search for only the last name (basically; problems arise when you have multiple names, multiple spaces etc). LIKE "ABC%" would then search for a last name starting with ABC.
You cannot use a fixed index as names that are more than 3 or less than 3 characters long would not return properly as you suggest.
However, as Zane said, it's a much better practise to use seperate fields.
If it is a MyIsam table, you may use Free text search to do the same.
You can use the REGEXP operator:
SELECT * FROM user WHERE name REGEXP "ABC$"
http://dev.mysql.com/doc/refman/5.1/en/regexp.html
I have a mysql table with a list of keywords such as:
id | keywords
---+--------------------------------
1 | apple, oranges, pears
2 | peaches, pineapples, tangerines
I'm trying to figure out how to query this table using an input string of:
John liked to eat apples
Is there a mysql query type that can query a field with a sentence and return results (in my example, record #1)?
One way to do it could be to convert apple, oranges, pears to apple|oranges|pears and use RLIKE (ie regular expression) to match against it.
For example, 'John liked to eat apples' matches the regex 'apple|orange|pears'.
First, to convert 'apple, oranges, pears' to the regex form, replace all ', ' by '|' using REPLACE. Then use RLIKE to select the keyword entries that match:
SELECT *
FROM keywords_table
WHERE 'John liked to eat apples' RLIKE REPLACE(keywords,', ','|');
However this does depend on your comma-separation being consistent (i.e. if there is one row that looks like apples,oranges this won't work as the REPLACE replaces a comma followed by a space (as per your example rows).
I also don't think it'll scale up very well.
And, if you have a sentence like 'John liked to eat pineapples', it would match both of the rows above (as it does have 'apple' in it). You could then try to add word boundaries to the regex (i.e. WHERE $sentence RLIKE '[[:<:]](apple|oranges|pears)[[:>:]]'), but this would screw up matching when you have plurals ('apples' wouldn't match '[wordboundary]apple[wordboundary]').
Hopefully this isn't more abstract than what you need but maybe good way of doing it.
I haven't tested this but I think it would work. If you can use PHP you can use str_replace to turn the spaces into keyword LIKE '%apple%'
$sentence = "John liked to eat apples";
$sqlversion = str_replace(" ","%' OR Keyword like '%",$sentence );
$finalsql = "%".$sqlversion."%";
the above will echo:
%John%' OR Keyword like '%liked%' OR Keyword like '%to%' OR Keyword like '%eat%' OR Keyword like '%apples%
Then just combine with your SQl statement
SQL ="SELECT *
FROM keywords_table
WHERE Keyword like" . $finalsql;
Storing comma delimited data is... less than ideal.
If you broke up the string "John liked to eat apples" into individual words, you could use the FIND_IN_SET operator:
WHERE FIND_IN_SET('apple', t.keywords) > 0
The performance wouldn't be great - this operation is better suited to Full Text Search.
I'm not aware of any direct solution to that type of query. But Full Text Search is a possibility. If you have a full-text index on the field of interest then a search with OR between each word in the sentence (although I think the OR operator is implied) would find that record ... but it might also find more than you want too.
I really don't think what you are looking for is completely possible but you can look into Full Text Search or SOUNDEX. SOUNDEX, for example, can do something like:
WHERE SOUNDEX(sentence) = SOUNDEX('%'+keywords+'%');
I have never tried it in this context but you should and let me know how it works out.