Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mysql like to match complete word or beginning of word on string

Tags:

mysql

sql-like

Given a search string I need to select every record where (in the field the search is performed on) there is at least one word that begins with the given text.

For example:

'John Doe'

Have to be be selected with search strings like:

'joh'
'do'
'JOHN doe'

Have not to be selected with

'ohn'
'oe'

I need (possibly) to avoid full text search.

What I've found to work is

$query = 'SELECT * FROM MYTABLE WHERE SEARCHFIELD LIKE "' . $searchText . '%"'
                                . 'OR SEARCHFIELD LIKE "% ' . $searchText . '%"'

I'm asking if there is a better way to do that.

(for "better way" I mean better performance or same performance but more elegant)

Also, as the query will be built up with a prepared statement, how should I unescape LIKE metacharacters in the search string?

like image 850
Paolo Avatar asked Oct 31 '13 22:10

Paolo


People also ask

How do I match a string in MySQL?

STRCMP() function in MySQL is used to compare two strings. If both of the strings are same then it returns 0, if the first argument is smaller than the second according to the defined order it returns -1 and it returns 1 when the second one is smaller the first one.

What is pattern matching in MySQL?

SQL pattern matching enables you to use _ to match any single character and % to match an arbitrary number of characters (including zero characters). In MySQL, SQL patterns are case-insensitive by default. Some examples are shown here. Do not use = or <> when you use SQL patterns.

How do I get the first word in MySQL?

To select first word in MySQL query, you can use SUBSTRING_INDEX().

How do I find a word in a string MySQL?

LOCATE() function MySQL LOCATE() returns the position of the first occurrence of a string within a string. Both of these strings are passed as arguments. An optional argument may be used to specify from which position of the string (i.e. string to be searched) searching will start.


2 Answers

As already stated in the question the query

$query = 'SELECT * FROM MYTABLE WHERE SEARCHFIELD LIKE "' . $searchText . '%"'
                                . 'OR SEARCHFIELD LIKE "% ' . $searchText . '%"'

works for matching records where the SEARCHFIELD contains a word that begins with (or is equal to) $searchText


Regarding performance I've made a test on my development machine MBP 2,2 GHz i7 quad core:

Searching for a word on 4.000 records takes around 40 milliseconds.

Records are normally indexed (no fulltext).

I have few thousands records and the query doesn't run very often so for me is good.
The solution may not be suitable for other contexts.


To build a prepared statement with the above query I used the technique described here:

Escaping MySQL wild cards

The resulting code is as follows:

function like($s, $e)
{
    return str_replace(array($e, '_', '%'), array($e . $e, $e . '_', $e . '%'), $s);
}

/* ... */

/* create a prepared statement */
$stmt = $mysqli->prepare(
    'SELECT * FROM MYTABLE WHERE SEARCHFIELD LIKE ? ESCAPE "=" OR SEARCHFIELD LIKE ? ESCAPE "="'
); 

if( $stmt )
{
    /* escape the text */
    $escSearchText = like( $searchText, "=" );

    /* 'like' parameters */
    $like1 = $escSearchText . "%";
    $like2 = "%" . $escSearchText . "%";

    /* bind parameters for markers */
    $stmt->bind_param( "ss", $like1, $like2 );

/* ... */
like image 81
Paolo Avatar answered Sep 19 '22 19:09

Paolo


Use this:

$query = "SELECT * FROM MyTable WHERE searchfield LIKE CONCAT('%', ?, '%')";

You don't need the OR condition -- if a field matches search%, it will also match %search%.

like image 24
Barmar Avatar answered Sep 18 '22 19:09

Barmar