I'm trying to search for a word in a string in mysql database using PHP.
the issue that I am having is that it searches and spits out the result on my PHP page but any word that is close to the searched word is also gets a result on my page.
to explain this better, lets say I have a string which is like this:
women's clothing
now if i search for a word which is women the results are being displayed on my page correctly But If i search for the word men the same results are being displayed on my page because the word women has the word men in it.
this is my current sql query:
SELECT id, category_name, image_url FROM data WHERE `category_name` LIKE '%$sub%' GROUP BY category_name
I tried to change '%$sub%' to '$sub' but that doesn't return any results at all!
could someone please advise on this?
Edit:
the strings in the category_name column vary and they cannot be changed since they are coming from an external API.
these strings could vary. so one might look like Women's Dresses & Skirts and another one might look like Women's shoes and another one might look Women's bags and another one might look like men's shoes etc etc....
so what i need to do is to display all the results for the keyword women and display the results for all the men. I hope that makes sense.
but at the moment, the results of men and women being displayed at the same time because the word Women has the word Men in it as I explained above.
You can do this with MySQL's REGEXP operator, using word match.
SELECT ... WHERE column REGEXP '[[:<:]]$sub[[:>:]]' ...
okay guys, thanks for all your inputs. this is how I did it and its working now:
SELECT id, category_name, aw_image_url FROM data WHERE category_name RLIKE '[[:<:]]".$sub."[[:>:]]' GROUP BY category_name
The thing with what you want, is that you want men's clothing to show up but nothing that has something like women. The only difference between these 2 results is that woMEN has characters in front of it and MEN's clothing has characters after.
Mrun his idea is if you want to search for the exact word followed by nothing. So when you use: LIKE '% $sub %' only results that have the word MEN followed by nothing and nothing in front of the word MEN directly. There has to be a space in between.
Now for your result to work, you can use: LIKE $sub% (without the space at the end), however this does mean the word MEN can be followed by anthing. So for example the word MENACE would show up. If you want specific characters only allowed like #mrun suggested, you can add anything between $sub and the % sign. You'd have to escape it though.
EDIT:
Now that I think of it, you'd probably want MENS to be allowed as well but that means you'll have to choose your own conditions cause there's no way for MYSQL to automatically detect that the plural form of a word is allowed as well etc.
There are several options for this. Here's one of them:
SELECT id, category_name, image_url FROM data WHERE `category_name` LIKE '% $sub %' OR `category_name` LIKE '% $sub' OR `category_name` LIKE '$sub' OR `category_name` LIKE '$sub %' OR `category_name` LIKE '% $sub\' %' OR `category_name` LIKE '% $sub' OR `category_name` LIKE '$sub\'' OR `category_name` LIKE '$sub\' %' GROUP BY category_name
Another way to do this is to use the MATCH AGAINST, but you will need to use the FULLTEXT index, here's how:
SELECT id, category_name, image_url FROM data WHERE MATCH (`category_name`) AGAINST ('+$sub' IN BOOLEAN MODE) GROUP BY category_name
Related
i am selecting data from sql by this command:
the command can contain more then one words like
select * from table where title like '%deadpool%' ////1
or
select * from table where title like '%deadpool%' && like '%world%' ////2
so this show results like :
*****************1*************
thenewdeadpoolishere
deadpool
*****************2*************
.deadpool.world.
deadpool world
now, i want to order the list as follows :
*****************1*************
deadpool
thenewdeadpoolishere or whatever
*****************2*************
deadpool world
cdsghjvjdhgdeadpoolvworlddsbvs or whatever
the thing is i want to order it somehow that if the whole word of searched term is present in the result then it should show up first.
I suspect you are looking for:
select t.*
from table t
where title like '%deadpool%' and
title like '%world%'
order by ((title like '%deadpool%') + (title like '%world%')) desc;
However, it is quite likely that you really want full text search, with order by relevancy. You can check the documentation to see if this is what you really want.
I´m currently working on a query that must pull up titles ordered by
Exact match,
Followed by Highest amount of matched words first,
Followed by First word in query is first word in title,
Followed by Alphabetical order.
Something like this:
SELECT title
FROM title
WHERE title LIKE '%keyword%' OR LIKE '%keyword1%' OR LIKE '%keyword2%'
order by
case when title == 'keyword' then 0 else 1 end asc,
((title like '%keyword1%') + (title like '%keyword2%')) desc,
case when title like 'keyword1%' then 0 else 1 end asc,
title asc;
I tested with 8 titles.
Search: "Buford Christmas".
Result:
Buford Christmas
Christmas Buford
Mr Buford
Mr Buford
Buford and Lisa
Lisa Christmas
Me Christmas
Me Buford Lisa.
I need to find a way to sort the titles so that "Buford and Lisa" should be before "Mr Buford".
They keyword in the query may have any number of sub-keywords, causing the code in the MySQL statement to change dynamically. My example code was generated with a keyword that has 2 sub-keywords. The part that seems not to be working is: "case when title like 'keyword1%' then 0 else 1 end asc" I am wondering if the code is in the wrong position in the comma delimited order sequence or if I should assign different numbers to 'then' and 'else'.
About my select code:
In my select statement if the keyword is "Buford Christmas" it's broken into "Buford" and "Christmas" and "Buford Christmas".
About this part of order code:
((title like '%keyword1%') + (title like '%keyword2%')) desc,
MySQL treats boolean expressions as numbers, with true being 1. So, this counts the number of matches.
select title
from books
where title like '%buford christmas%'
or title like '%buford%'
or title like '%christmas%'
order by
case
when
title = 'buford christmas' then 1
when
title like '%buford%' and title like '%christmas%' then 2
when
title like 'buford%' then 3
when
title like '%buford%' then 4
when
title like 'christmas%' then 5
when
title like '%christmas%' then 6
end
asc;
This will do what you're looking for. Obviously substitute variables for the literals there. It prioritises results as such:
Books with title that EXACTLY matches the keywords
Books with titles that CONTAIN BOTH keywords
Books with titles that START with the first keyword
Books that CONTAIN the first keyword
Books that END with the last keyword
Books that CONTAIN the last keyword
Demo: http://sqlfiddle.com/#!9/ec62a/7
edit
You may also want to consider a fulltext index, eg: create fulltext index ftx_title on books(title), you could then run your query as such:
select *
from books
where match(title)
against ('buford christmas' in boolean mode);
Which would make crafting your queries for keywords quite a bit simpler
I have a table that contains 3 text fields, and an ID one.
The table exists solely to get collection of ID's of posts based on relevance of a user search.
Problem is I lack the Einsteinian intellect necessary to warp the SQL continuum to get the desired results -
SELECT `id` FROM `wp_ss_images` WHERE `keywords` LIKE '%cute%' OR `title` LIKE '%cute%' OR `content` LIKE '%cute%'
Is this really enough to get a relevant-to-least-relevant list, or is there a better way?
Minding of course databases could be up to 20k rows, I want to keep it efficient.
Here is an update - I've gone the fulltext route -
EXAMPLE:
SELECT `id` FROM `wp_ss_images` WHERE MATCH (`keywords`,`title`,`content`) AGAINST ('+cute +dog' IN BOOLEAN MODE);
However it seems to be just grabbing all entries with any of the words. How can I refine this to show relevance by occurances?
To get a list of results based on the relevance of the number of occurrences of keywords in each field (meaning cute appears in all three fields first, then in 2 of the fields, etc.), you could do something like this:
SELECT id
FROM (
SELECT id,
(keywords LIKE '%cute%') + (title LIKE '%cute%') + (content LIKE '%cute%') total
FROM wp_ss_images
) t
WHERE total > 0
ORDER BY total DESC
SQL Fiddle Demo
You could concatenate the fields which will be better than searching them individually
SELECT `id` FROM `wp_ss_images` WHERE CONCAT(`keywords`,`title`,`content`) LIKE '%cute%'
This doesn't help with the 'greatest to least' part of your question though.
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.
keyword = house
SELECT * FROM products WHERE description LIKE '%house%'
This query also returns records having keyword, for example, courthouse, but I want to look for house only. How do I search anywhere in the description for "house" only?
Thanks.
UPDATE
just for more clarification ..
actually house, can be at
- the start of the description .. "House for sale..",
- can be quoted -- "house", 'house'
- can have exclamation .. house!!!, house!
- others - house? etc ..
this is why I used %house%
Are you looking for longs strings containing the whole word?
Search for "whole word match" in MySQL
SELECT * FROM products WHERE description rlike '[[:<:]]house[[:>:]]'
rlike is synonim for REGEXP.
[[:<:]] denotes the start of the word and the
[[:>:]] end of the word.
It works for all your requirements (case insensitive, with quoted words or words ending, or begging, with exclamation points and other non-letter characters)
The % before and after will search any matching text before and after the search keyword, try this instead for exact search:
SELECT * FROM products WHERE description = 'house'
Simple thing only house means, use this
SELECT * FROM products WHERE description = 'house'
If you want any word contain house in backside means use this,
SELECT * FROM products WHERE description LIKE '%house'
If you want any word contain house in frontside means use this,
SELECT * FROM products WHERE description LIKE 'house%'
If you want any word contain house in anywhere in description means use this,
SELECT * FROM products WHERE description LIKE '%house%'
Try a space around the keyword:
SELECT * FROM products WHERE description LIKE '% house %' OR description LIKE 'house %' OR description LIKE '% house' OR description LIKE '% house%'
Edit: added more options in search. The last one would allow for house. or house,, though something like housecat would also match. Regex would work best here. This solution came from Astandar, who deleted his answer.