What are some ways to improve this long mysql search query? - php

Looking to improve this mysql select statement for a search query:
Select * from table WHERE ( user = '$search_query'
OR user LIKE '$search_query %'
OR keyword LIKE '$search_query'
OR tag LIKE '$search_query'
OR tag LIKE '% $search_query'
OR tag LIKE '% $search_query%'
OR tag LIKE '$search_query%'
OR REPLACE(question, ',' ,'') LIKE '$search_query %'
OR REPLACE(question, ',' ,'') LIKE '% $search_query'
OR REPLACE(question, ',' ,'') LIKE '% $search_query %'
OR REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(question, '\'', ''), ',', ''), '.',''), ':',''), ';',''), '!',''), '?','') LIKE '%$search_query%'
)
The reason it's broke down the way it is, is because say if someone searches for "art", I don't want it showing results for "heart" as well.
I really need to have of these same functions but running fewer resources.

If your table is MyISAM, you can create a FULLTEXT index on it:
CREATE FULLTEXT INDEX fx_mytable_user_tag_question ON mytable (user, tag, question)
SELECT *
FROM mytable
WHERE MATCH(user, tag, question) AGAINST ('+some*' IN BOOLEAN MODE)
This query will return some and something but not awesome.
Actually, the first step (creating the index) is not required, however, it will speed up the queries and allow more complex searches (not limited to BOOLEAN MODE) and relevance ranging.
By default, minimal length of a search query is 4 characters, so art mentioned in your example would not be found.
To work around this, you will have to change parameter ft_min_word_len in server settings.

It looks like
OR tag LIKE '$search_query'
OR tag LIKE '$search_query%'
would return identical results to only running
OR tag LIKE '$search_query%'
Same with
OR tag LIKE '% $search_query'
OR tag LIKE '% $search_query%'
Searching around for this question, I learned that MySQL supports regular expression searches. Using these, if you are able to specify what pattern the % should match. This would help with all those pesky spaces, because you could just use \s?.

Restructure your database such that tags are stored in a separate table, with one row for each tag on a question, so that you can run a query like:
SELECT * FROM question
WHERE question_id IN (
SELECT question_id FROM question_tags WHERE tag = '$search_query'
) OR <...>
Depending on how you want search keywords to work, you may be able to use a similar solution there.

Related

How to search the multiple keywords in multiple columns? [duplicate]

I'm trying to make a search feature that will search multiple columns to find a keyword based match. This query:
SELECT title FROM pages LIKE %$query%;
works only for searching one column, I noticed separating column names with commas results in an error. So is it possible to search multiple columns in mysql?
If it is just for searching then you may be able to use CONCATENATE_WS.
This would allow wild card searching.
There may be performance issues depending on the size of the table.
SELECT *
FROM pages
WHERE CONCAT_WS('', column1, column2, column3) LIKE '%keyword%'
You can use the AND or OR operators, depending on what you want the search to return.
SELECT title FROM pages WHERE my_col LIKE %$param1% AND another_col LIKE %$param2%;
Both clauses have to match for a record to be returned. Alternatively:
SELECT title FROM pages WHERE my_col LIKE %$param1% OR another_col LIKE %$param2%;
If either clause matches then the record will be returned.
For more about what you can do with MySQL SELECT queries, try the documentation.
If your table is MyISAM:
SELECT *
FROM pages
WHERE MATCH(title, content) AGAINST ('keyword' IN BOOLEAN MODE)
This will be much faster if you create a FULLTEXT index on your columns:
CREATE FULLTEXT INDEX fx_pages_title_content ON pages (title, content)
, but will work even without the index.
1)
select *
from employee em
where CONCAT(em.firstname, ' ', em.lastname) like '%parth pa%';
2)
select *
from employee em
where CONCAT_ws('-', em.firstname, em.lastname) like '%parth-pa%';
First is usefull when we have data like : 'firstname lastname'.
e.g
parth patel
parth p
patel parth
Second is usefull when we have data like : 'firstname-lastname'. In it you can also use special characters.
e.g
parth-patel
parth_p
patel#parth
Here is a query which you can use to search for anything in from your database as a search result ,
SELECT * FROM tbl_customer
WHERE CustomerName LIKE '%".$search."%'
OR Address LIKE '%".$search."%'
OR City LIKE '%".$search."%'
OR PostalCode LIKE '%".$search."%'
OR Country LIKE '%".$search."%'
Using this code will help you search in for multiple columns easily
SELECT * FROM persons WHERE (`LastName` LIKE 'r%') OR (`FirstName` LIKE 'a%');
Please try with above query.

Using the MySQL like statement

Hello i am trying to get the like statement working however it will only work if its an exact match where as im am hoping to show all matches. So lets say you search "and" in the search bar, i want it to come back with all posts that have the word and in the title Below is the code
SELECT * FROM `Posts` WHERE title LIKE 'and'
Just trying to get this working in the phpmyadmin with the sql tab before i bother creating the actual full script.
Does anyone know how i can get the above statement to show all posts with and in the title?
Thanks for the help.
You have to put % before and after and.
SELECT * FROM `Posts` WHERE title LIKE '%and%'
Use:
SELECT * FROM `Posts` WHERE title LIKE '% and %'
Doing something like:
SELECT * FROM `Posts` WHERE title LIKE '%and%'
will include anything with and in it; sandy, for example.
try this placing % symbol
SELECT * FROM `Posts` WHERE title LIKE '%and%'
Do like this:
SELECT * FROM `Posts` WHERE title LIKE '%and%'
MySQL provides two wildcard characters for using with the LIKE operator, the percentage % and underscore _.
The percentage ( %) wildcard allows you to match any string of zero or more characters.
The underscore ( _) wildcard allows you to match any single character
Suppose you want to search for posts whose title starts with character ‘ and‘, you can use the percentage wildcard ( %) at the end of the pattern
SELECT * FROM `Posts` WHERE title LIKE '%and%'
If you know the searched string is embedded inside in the column, you can use the percentage ( %) wildcard at the beginning and the end of the pattern
SELECT * FROM `Posts` FROM books WHERE title REGEXP '[[:<:]]and[[:>:]]';
With this fiddle you are going to learn the differences when you use the wildcard operator(%):
select bar from foo where bar like "%h";
select bar from foo where bar like "%h%";
select bar from foo where bar like "h%";
Check the result here: http://sqlfiddle.com/#!2/1bc45f/2

MySQL Search String with Spaces Using LIKE

I'm building a search on my site and I noticed it doesn't work when you enter more than one word into the search. Here's the gist of the query:
SELECT * FROM `blog` WHERE `content` LIKE '%$keyword%' OR `title` LIKE '%$keyword%' ORDER BY `id` DESC
The weird things is that when I test the query in phpMyAdmin it returns the expected results. On my website however, no results are found.
I tried replacing spaces in the keyword with %s, but that didn't change anything.
The problem is that LIKE does pattern matching rather than actually search for keywords. You should create a fulltext Index on your database columns and use WHERE MATCH keywords AGAINST column. That will properly search for all keywords in any order and be a lot faster anyway.
I just tried this in my database and using LIKE in the query is more than 66 times as fast than using MATCH with fulltext index. I'm using two tables which are "connected" to each other. One is tags and the other one is products.
So what I did was that I added a fulltext index to the tag column in the tags table and performed the match against that column. The query than joins the products and then spits out some data about the item. That took about 4 seconds with ~3000 products & ~3000 tags.
I then tried it by first exploding the search string by whitespaces, and then imploding the result with %' OR tags.tag LIKE '%. This took about 0,06 seconds with the same amount of products and tags.

MySQL: Find similar repeated entries

Given my table
id | name
01| Test Name
02| Name Test
03| Another name
...
...
nn| Test string
I'd like to do the following, for each entry, read the first word, until a space, so in this example i would read Test, then, find all similar entries which contain Test anywhere on the string, then continue with Name, Another, and so on.
I don't want to do this manually, as I'll have to make a lot of queries, the idea is the data is imported from an old excel spreadsheet and the client wants to get repeated names, so Test Name, Test Something Name and Name Test are potential similar names.
You want to run a query, select all the names, return that to php, then loop through it, parse the string into separate words, and run a query with a fulltext index.
here's something to get you started.
http://www.databasejournal.com/sqletc/article.php/1578331/Using-Fulltext-Indexes-in-MySQL---Part-1.htm
Here's my db solution:
SELECT *
FROM princess a
INNER JOIN (SELECT
DISTINCT CASE
WHEN name LIKE '% %'
THEN SUBSTR(name, 1, LOCATE(' ', name) - 1)
ELSE name
END AS 'name'
FROM princess) b ON a.name LIKE CONCAT('%', b.name ,'%')
This will find the DISTINCT names (before a space) and then JOIN to the original table using LIKE.
You may also consider using INSTR(a.name, b.name) in place of b.name LIKE CONCAT('%', a.name ,'%') depending on how your EXPLAIN looks.
There are a ton of examples of how to split a string into multiple rows in MySQL, e.g. this one.
After that, you can find the exact matches easily. If you want non-exact matches, check out SOUNDEX()

Match tags in MYSQL

I wanted to know how can you search in tags p.s.
I have a table where there is a column for tags "bar,barmen,drink".
In search for example people search for barmen drink, how do I match this, I tried
LIKE, INSTR() but no luck, the point is that tags column content doesn't have spaces between.
It's like "bar,barmen,drink" not like "bar, barmen, drink"
Any help..?
Why not have a separate tags table, with
id int(11) auto_increment
post_id int(11)
tag text
Then, have one tags row for each tag.
This is a problem inherent with this type of design. Short of changing how you store the data, you'd have to do a search like this:
SELECT * FROM my_table WHERE CONCAT(',', tags, ',') LIKE '%,bar,%';
EDIT: Actually, I just double-checked, and you can use regexp like so:
SELECT * FROM my_table WHERE tags REGEXP '[[:<:]]bar[[:>:]]';
Which should be quite a bit faster.

Categories