Universal searchbox in vb.net & checking from multiple tables - mysql

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 '?%'

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

is there a "best way" to short circuit a mysql query

I have a situation where I'm assembling a query based on user provided criteria and want to figure out what the most efficient way is to do this.
If I have a table that looks like this:
int id | varchar phone | varchar email | varchar RFID
and the user will pass in an array which defines the order (and items) with which they'd like to look up a user which *could look like this:
["id","email","phone"]
or it could look like this:
["email"]
or it could look like this:
["phone","rfid"]
or any other possible combination of those 4 fields.
Based on what I receive I need to look the user up in the order in which these fields arrived and if I find a match, I don't want to keep looking.
In other words if the input is
["email","rfid","phone"]
and I look into the db and find a user with the provided email, I don't want to keep looking to see if their rfid also matches, I just want to return said user.
However, if I don't find such an email, then I want to move on to the rfid.
So, in the various tests I've done (mostly playing with a case statement in the where clause) my results have been really terrible. Frequently taking almost a second to return a value, as opposed to taking <50ms when I simplify the where to search for the individual field.
I should note that all these fields are indexed.
So... my question is, should I just bite the bullet and make as many sql calls as there are items in the incoming array, or is there some really efficient way to structure a single query that will not bog down the system as my various attempts have.
I recognize that this may be too abstract a question, but am hoping that there's some mechanism for just such a use that I'm simply overlooking.
I don't think there's any good way to do a short-circuit in SQL. You can construct a WHERE clause that uses OR to combine the critiera, but doing this generally prevents it from using the indexes. You can use a UNION like this:
SELECT * FROM
(SELECT 1 precedence, table.*
FROM table
WHERE field1 = 'value'
UNION
SELECT 2 precedence, table.*
FROM table
WHERE field2 = 'value'
...
) x
ORDER BY precedence
LIMIT 1
where you replace field1, field2, etc. with the field names from the input array. This will produce the desired results in one query, but it will have to perform all the sub-queries, it won't short-circuit.
The best solution is probably to solve it in the application code. Loop through the fields in the input, and perform a query for just that field. When you get a result, break out of the loop and return it.

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.

MySQL: Selecting most similar value?

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%'

How to write mysql query to search database?

I'm own a wallpaper website and I'm trying to write a search feature that will search the database for the terms the user is searching for. I have 2 fields in the database I'm searching against TAGS and NAME
The current way I'm doing it is I take the search term divide it up into multiple words and then search the database using those terms. So if a user searches for "New York" my query will look like this
SELECT * FROM wallpapers
WHERE tags LIKE '%New%' OR name LIKE '%new%'
or tags LIKE '%York%' OR name LIKE '%York%'
The issue with that of course is that anything with the term new in it will be pulled up also like say "new car" etc. If I replace the query above with the following code then it's too vague and only like 2 wallpapers will show up
SELECT * FROM wallpapers
WHERE tags LIKE '%New York%' OR name LIKE '%New York%'
Does anyone have a better way to write a search query?
Looks like you want to introduce the concept of relevance.
Try:
select * from (
SELECT 1 as relevance, * FROM wallpapers
WHERE tags LIKE '%New York%' OR name LIKE '%New York%'
union
select 10 as relevance, * FROM wallpapers
WHERE (tags LIKE '%New%' OR name LIKE '%new%')
and (tags LIKE '%York%' OR name LIKE '%York%')
union
select 100 as relevance, * FROM wallpapers
WHERE tags LIKE '%New%' OR name LIKE '%new%'
union
select 100 as relevance, * FROM wallpapers
WHERE tags LIKE '%York%' OR name LIKE '%York%'
)
order by relevance asc
By the way, this will perform very, very poorly if your database grows too large - you want to be formatting your columns consistently so they're all upper case (or all lower case), and you want to avoid wildcards in your where clauses if you possibly can.
Once this becomes a problem, look at full text searching.
Perhaps this is a really dumb question, but could be following possibly what you want?
SELECT * FROM wallpapers
WHERE ( tags LIKE '%New%' OR name LIKE '%new%' )
and ( tags LIKE '%York%' OR name LIKE '%York%' )
This searches for wallpapers which must have both words but anywhere.
Warning Beware of SQL injection this way, when searching for "words" like new'york or new%york. Perhaps the most easy way is to treat all nonalpha/nonnumeric characters as spaces when splitting, such that new#york and similar becomes new and york.
Notes about searching:
Searching this way in databases is plain overkill (full table scan). As long as you only have a few wallpapers this is not a bigger problem. Nearly all current cheap hardware should be able to search through a million wallpapers within a second or so, as long as the database fits into memory.
However with bigger sites where the tags and name information exceeds available RAM, you certainly get a problem. Then it is time to try some other way to search. However what to do heavily depends on the expected use pattern, so to answer that more information is needed.
You can use your first query to do a first selection and after that your can rank the results : a wallpaper with both keywords "New" and "York" will be ranked higher than a wallpaper with only one of the keywords.
If the second query only returns 2 wallpaper, can you put some example of the tags/name of the wallpaper not returned by the query but that you would like to have ?
Is it a problem of uppercase letters ? Spaces ?
I believe you may benefit from Full text indexes. Read up on mysql full text search. You will need to be using MyISAM engine for your tables.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html