MySQL: Selecting most similar value? - mysql

So I have a table with peoples names.
I need to code a query that selects the person with the name most similar to the given one.
For example:
SELECT * FROM people WHERE name='joen'
'joen' doesnt exist in the table, so it will return John, which exists in the table.
What's the MySQL command for this?

You may be looking for SOUNDEX and SOUNDS_LIKE
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

The Levenshtein algorithm computes the "distance" between words: Levenshtein MySQL function
You can use it like this if you add that function:
SELECT * FROM people WHERE levenshtein('joen', `name`) BETWEEN 0 AND 4;

I'm not an expert on this, but this is no trivial matter. By "similar" do you mean it might be one or 2 letters off, or do you mean "Jon" should match "Jonathan" and "Bill" should match "William"?
If the latter, you might want to find or build a table that maps names/nicknames to eachother, and do a search on that.
If it's misspellings, Levenshtein might be of assistance, but I don't know how you'd integrate that in an SQL query.

The LIKE Keyword might help you
SELECT * FROM people WHERE name LIKE 'jo%'
Selects users where name starts with "jo"
If you're programatticaly changing the query, you
can check for the "result" and query the database again
with the new Query by reducing the characters in the
"name" specified.
SELECT * FROM people WHERE name LIKE 'jones%'
SELECT * FROM people WHERE name LIKE 'jone%'
SELECT * FROM people WHERE name LIKE 'jon%'
SELECT * FROM people WHERE name LIKE 'jo%'

Related

How to make a good sql search with like

For years when I want my user to search some field in my database where he can type anything he wants I use an algorithm to break the words and search each word separetely... a mess.
For example, if the user types in the search box "aaa bbb ccc" I dont like using:
SELECT id
FROM table
WHERE description LIKE '%aaa bbb ccc%'
Cause sometimes the user types things out of order and the query above wouldng find. What I usually do is breaking the string and concatenating it with PHP so the result becomes:
SELECT id
FROM table
WHERE description LIKE '%aaa%'
AND description LIKE '%bbb%'
AND description LIKE '%ccc%'
But today after talk to a friend I was wondering if there is some native way to do this faster using MY SQL?
What you want to do is called full text search and most relational databases support it nowadays, including mysql.
I think you can use REGEXP. For example:
Select * from table where description REGEXP 'aaa|bbb|ccc'
FULLTEXT Searches are really fast.
INSTR or locate works better than REGEXP. But it depends on various factors.
More comparison here
SELECT * from table where INSTR(description, 'aaa') >0
SELECT * from table where LOCATE(description, 'aaa') >0

SQL OR statement in Wildcard

My current MySql wild card is LIKE '%A%B%'. This can return values that contain A and B.
Can anyone suggest how can I alter the wildcard statement to return values that contain either A or B.
Thanks in advance.
You can add as many like operator you want within the parenthesis with OR condition like below
select * from tablename where (column_name like '%test%' or same_column_name like '%test1%' or
same_column_name like '%test2%' or same_column_name like '%test3%')
For more info have a look at the below link.
SQL Server using wildcard within IN
Hope that helps you
You can use REGEXP
select * from Table1 where some_column REGEXP '[AB]'
there are lots of different ways in writing this as a regular expression, the above basically means containing A or B.
Generally you want to avoid using REGEXP and LIKE '%something' because the do not use indexes. Thus for large tables these operations would be unusable. When you want to do a search of this kind it's always best to stop and ask: "Have I got the best database design?", "Can I use full text search instead?"

Universal searchbox in vb.net & checking from multiple tables

My concept is little unclear. For my site I want to create a searchbox. And I will use Autocomplete function to check related keywords from database. So while typing matching word will come as suggestion. But I am not sure about how to check it through multiple tables. My concept is on health based site so there is different table for each sections like hospitals, doctors, laboratories, chemist etc. I just need guidance how should I do it?
You can use union queries to return autocomplete data for your textbox. For example, you could write a query that for a search term could do this:
select hospitals.name as name
from hospitals
where hospitals.name like '%?%'
UNION
select doctors.lastname as name
from doctors
where doctors.lastname like '%?%'
UNION
select laboratories.labname as name
from laboratories
where laboratories.labname like '%?%'
UNION
...
Be careful though: the performance of this could degrade fast, especially for "contains" searches like the example above ( like '%?%').
A faster query would be a "starts with" which would change the like clause in the query above to like '?%'

is there an "inverse" function to IN() in MySQL?

The scenario is this: in a table A, I have one column "tags", which is varchar(255).
In this column I store numbers, separated by commas, like this:
2,14,31,33,56
etc. there can be none, one, or several.
and I need to make a SELECT query that will return rows that have a certain number in this field. right now I'm using this method (don't be alarmed, I know its a poor way.. that's why I'm asking for help!). for example, let's assume the number I want to check is 33. the query is:
SELECT * FROM table_a WHERE
tags LIKE "%,33,%" OR tags LIKE "33,%" OR tags LIKE "%,33" OR tags LIKE "33"
I'm no expert but I know this can't be the method. The first question that comes to mind is: is there a command similar to IN() but that works the other way around?
I mean, can I tell it "find rows where 'tags' contains value 33" ?
When asking this question, I can see that there may be another field type other than varchar(255) to contain this type of data (an array of numbers, after all)
Is there a GOOD and efficient way of doing this? my method works for small tables, yes, but if the table grows.. (say, 10k rows, 50k, 300k ... ) this is obviously a problem.
The function that you want is find_in_set():
SELECT *
FROM table_a
WHERE find_in_set(33, tags) > 0;
You can simplify your like statement to be:
SELECT *
FROM table_a
WHERE concat(',', tags, ',') LIKE '%,33,%';
Neither of these can make use of an index. Having a separate table with one row per entity and per tag is the right way to go (but I think you know this already).

Fulltext search that isn't exact match

I have a MySQL-table called "customers1" running engine MyISAM. I've created a full text index on the columns name,adress and zip. Now one of the customers in that table is me. I spell my name "Gildebrand". Now i can't expect that the users can spell my name correctly, many might write "Glidebrant", but still want to find my. How could i do that search in SQL?
If i run the following query right now
SELECT * FROM customers1 WHERE MATCH(name,adress,zip) AGAINST('Gildebrand')
It finds me, of course. But if i misspell, "Glidebrand", it doesn't find me. What would be the best approach to this?
I would say the closest you can get from such a result if by using SOUNDEX() http://www.w3resource.com/mysql/string-functions/mysql-soundex-function.php
I have a generic search similar to yours. Here's basically what I do:
SELECT * FROM customers1 WHERE MATCH(name,adress,zip) AGAINST('?')
UNION
SELECT * FROM customers1 WHERE name LIKE ('?%')
This allows the user to just enter a prefix also.
If the user realizes they can't spell your name, but they're sure it starts with Gil, then they can just type that.
You can add additional UNION clauses if you want to support prefixes on other columns too.