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
Related
I am making an eCommerce website I am using PHP and Mysql and I have some products name in table named product. How can I make a search system by which if I type "Wallnuts", it should return all results having word "wallnut, walnut, walnuts" and word with same pronunciation like "valnuts" and sorted as best matching result first. For this I am trying this by this query :
select product_name,photo,in_stock,sell_price
from $tbl_product
where product_name like '%".$q."%'
ORDER BY (CASE WHEN product_name LIKE '".$q."%' THEN 1
WHEN product_name LIKE '%".$q."%' THEN 2 ELSE 3
END) limit 0,10
Where $q is search string. By this query I am getting result but with only exact word match.
I need result like on Bigbasket.com for word wallnuts, wallnut, walnts, valnuts.
The closest you can try is SOUNDEX() function in MYSQL.
select * from mytext
where soundex(val) LIKE CONCAT('%',SOUNDEX('wallnut'),'%')
This gives me wallnuts, wallnut, walnts.Check Demo here
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
I am searching from 3 tables currently (will search in more after sorting this out). This query brings all the results in the order of the tables listed in query. Whereas I want to get the most relevant search results first.
(Select name, url, text, 'behandlinger_scat' AS `table` from behandlinger_scat where name LIKE '%KEYWORD%' OR text LIKE '%KEYWORD%')
UNION
(Select name, url, text, 'hudsykdommer_scat' AS `table` from hudsykdommer_scat where name LIKE '%KEYWORD%' OR text LIKE '%KEYWORD%')
UNION
(Select name, url, text, 'om_oss' AS `table` from om_oss where name LIKE '%KEYWORD%' OR text LIKE '%KEYWORD%')
Any help would be appreciated.
You can use a method to order by the points you dynamically give the results, as in this example (you will need to alias your tables so SQL will understand what column you're referring to):
ORDER BY
CASE WHEN name LIKE table.keywords THEN 100 ELSE 0 END +
CASE WHEN name LIKE table2.keywords THEN 10 ELSE 0 END +
CASE WHEN text LIKE table2.keyword THEN 1 ELSE 0 END
DESC
This is merely an example, but the concept is the following:
You decide how many "points" each "match" will receive (e.g name matches keyword is 100 points, text matches it - a little less) then, each row "accumulates" points with correlation to its matches, and the row with the most points shows first.
I have this problem and I dont know where to start.
For example I have this in my database [this is just sample database
]
id word
1 adore
2 and
3 apple
4 asore
5 banana
6 bate
7 beat
8 busy
How can I sort it and filter it so I only view words beginning with 'A'?
id word
1 adore
2 and
3 apple
4 asore
You can use the SQL-LIKE-Statement.
SQL: SELECT DISTINCT word FROM Table WHERE word LIKE 'A%'
This only returns words that start with an a.
This is lot simpler than you think. You can use SQL LIKE operator.
SELECT * FROM table WHERE word LIKE 'a%' ORDER BY word;
select id, word
from your_table
where word like 'a%'
order by id
or
select id, word
from your_table
where substring(word, 1, 1) = 'a'
order by id
I want to show similar items using tags.
I have items table with itemid, itemname and itemtagids as columns. itemtagids has CSV tag ids.
Say in itemid 1, I have 3 tag ids 1,2,3 and in itemid 2 I have 4 tag ids 3,4,5,6 in itemid 3 I have 2 tag ids 2,3 and so on..
I want that for itemid 1 in similar items 3rd itemid should be shown first (because it has 2 matching) then itemid 2 and so on..
What i have used is:
SELECT itemid
FROM items
WHERE MATCH (itemtagids ) AGAINST ('2823' IN BOOLEAN MODE)
it does return results only in the case when there is one itemtagid in itemtags ids column.
sequence is something lie: 234,546,2823,342,5643 So, here 2823 is not an individual word but a complete string from 234,54...43
what should be done in this case where tags are in the form of ids and in CSV format.
It seems a FULLTEXT isn't the right search for your case. Try using regular expressions instead.
SELECT `itemid`
FROM `items`
WHERE `itemtagids` REGEXP '^2823$'
OE `itemtagids` REGEXP '^2823,'
OR `itemtagids` REGEXP ',2823$'
OR `itemtagids` REGEXP ',2823,';
EDIT: or perhaps you might do with a single regular expression, like:
SELECT `itemid`
FROM `items`
WHERE `itemtagids` REGEXP '[[:<:]]2823[[:>:]]';
Hope it helps!