MySQL SELECT LIKE or REGEXP to match multiple words in one record
Asked Answered
E

7

84

The field table.name contains 'Stylus Photo 2100' and with the following query

SELECT `name` FROM `table` WHERE `name` LIKE '%Stylus 2100%'

I get no results. Of course i would if i searched

SELECT `name` FROM `table` WHERE `name` LIKE '%Photo 2100%'

How can I select the record by searching 'Stylus 2100' ?

Thanks

Epicarp answered 1/2, 2012 at 16:31 Comment(2)
Caveat: This Question is about two words occurring in a particular order. Most of the Answers do not allow for matching "2100 Stylus".Scorper
If one of two ( or many) options, try select * from table1 where column1 REGEXP 'something|otherthing';Farly
A
130

Well if you know the order of your words.. you can use:

SELECT `name` FROM `table` WHERE `name` REGEXP 'Stylus.+2100'

Also you can use:

SELECT `name` FROM `table` WHERE `name` LIKE '%Stylus%' AND `name` LIKE '%2100%'
Antimasque answered 1/2, 2012 at 16:36 Comment(11)
Thanks, this way i won't get 'HP Laserjet 2100'. Sorry if my example was not the best.Epicarp
One of the repliers to the answer here compared LIKE / REGEX performance and found that LIKE performed better, FYI: https://mcmap.net/q/82454/-mysql-like-inLuff
@Amalgovinus thanks for the link, I wouldn't have thought so.. It's good to know :)Antimasque
What if I have 3 words ?Seaworthy
@Seaworthy in the first query .+ indicate any character (1 or more) between Stylus and 2100 if you want to add EPSON it would be EPSON.+'Stylus.+2100 in the second query you just need to add a new AND in the WHERE clauseAntimasque
Thanks @SERPRO. I know and I had tried ...but I am not getting the right result. But ... even with Stylus.+2100 I am not getting the right results ... with ^(.+EPSON.+2100.+)|^(.+2100.+EPSON.+).*$ I am geting the right LIKE results.Seaworthy
@Seaworthy See these examples sqlfiddle.com/#!9/53dbec0/1/0 sqlfiddle.com/#!9/53dbec0/2/0Antimasque
why not WHERE name LIKE '%Stylus%2100%'?Jotting
The first requires Stylus to come before 2100; the second lets them be in either order. So, they are "different" answers.Scorper
What about SELECT name FROM table WHERE name REGEXP 'stylus|2100|photo'Chrysanthemum
SELECT name FROM table WHERE name RLIKE 'Stylus|2100'Vanburen
B
30

I think that the best solution would be to use Regular expressions. It's cleanest and probably the most effective. Regular Expressions are supported in all commonly used DB engines.

In MySql there is RLIKE operator so your query would be something like:
SELECT * FROM buckets WHERE bucketname RLIKE 'Stylus|2100'
I'm not very strong in regexp so I hope the expression is ok.

Edit
The RegExp should rather be:

SELECT * FROM buckets WHERE bucketname RLIKE '(?=.*Stylus)(?=.*2100)'

More on MySql regexp support:
http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp

Bissell answered 7/12, 2012 at 12:21 Comment(6)
This regular expression does something different: it gets anything that contains either 'Stylus' or '2100', not necessarily both.Volley
I've improved my RegExpBissell
I was searching for a regexp only solution and this trick did it ^^,Dopey
By adding a | between the 2 () like this RLIKE '(?=.*Stylus)|(?=.*2100)' will give separate results -->> rows with Stylus only, rows with 2100 only OR rows with both... but not necessarily the 2 in the same row...Frisby
Did you try this? Never heard that MySql regex supports lookarounds.Superintendency
@bobblebubble - Good point; I think MySQL 8.0 and MariaDB 10.0 are when they got 'lookarounds' and lots of other esoteric regexps.Scorper
J
18

You can just replace each space with %

SELECT `name` FROM `table` WHERE `name` LIKE '%Stylus%2100%'
Jovanjove answered 1/2, 2012 at 16:45 Comment(5)
Thanks but this way i wouldn't get if i searched 'Photo Stylus 2100'Epicarp
haha! okay, that requirement was not specified on the question, "How can I select the record by searching 'Stylus 2100' ?"Jovanjove
I know this question is old, but is this not the most efficient solution? From what I can tell, this will match Photo Stylus 2100. It will match anything followed by Stylus followed by anything followed by 2100 followed by anything. If someone disagrees, please tell me why because it means I've fundamentally misunderstood something about like expressions.Wivina
@Wivina I'm a bit late, but % is like + in Regex, not *. It matches something, not anything, so won't match Photo Stylus 2100 but would match Photo Stylus 2100x.T
@T - Wrong. LIKE's % matches the empty string. So it is essentially identical to RLIKE's .*. Melvin's answer stands; Alessio first comment is wrong. It is trivial to test: SELECT 'Photo Stylus 2100' LIKE '%Stylus%2100%'; returns 1 (meaning true).Scorper
C
8

The correct solution is a FullText Search (if you can use it) https://dev.mysql.com/doc/refman/5.1/en/fulltext-search.html

This nearly does what you want:

SELECT * FROM buckets WHERE bucketname RLIKE '(Stylus|2100)+.*(Stylus|2100)+';

SELECT * FROM buckets WHERE bucketname RLIKE '(Stylus|2100|photo)+.*(Stylus|2100|photo)+.*(Stylus|2100|photo)+.*';

But this will also match "210021002100" which is not great.

Clarance answered 16/7, 2015 at 10:53 Comment(0)
H
1

you need to do something like this,

SELECT * FROM buckets WHERE bucketname RLIKE 'Stylus.*2100';

or

SELECT * FROM buckets WHERE bucketname RLIKE '(Stylus)+.*(2100)+';
Howsoever answered 22/6, 2018 at 8:47 Comment(1)
The second one gives allows the silly StylusStylus 210021002100 -- Why have the +??Scorper
M
0

Assuming that your search is stylus photo 2100. Try the following example is using RLIKE.

SELECT * FROM `buckets` WHERE `bucketname` RLIKE REPLACE('stylus photo 2100', ' ', '+.*');

EDIT

Another way is to use FULLTEXT index on bucketname and MATCH ... AGAINST syntax in your SELECT statement. So to re-write the above example...

SELECT * FROM `buckets` WHERE MATCH(`bucketname`) AGAINST (REPLACE('stylus photo 2100', ' ', ','));
Madcap answered 10/1, 2019 at 23:54 Comment(0)
P
0
SELECT `name` FROM `table` WHERE `name` LIKE '%Stylus % 2100%'
Peraea answered 12/3, 2019 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.