简体   繁体   中英

MySQL - alternative for like - regexp?

i have got over one milion record in my database table. When I use like is very slowly, when i use match against they lost some records.

I create help table:

tag_list

tag_id
tag_name

tag_rel_message

tag_id
messag_id

messages

message_id
message_text

in tag_list i add all words of $message_text - explode(" ", $message_text);

My new query is:

SELECT m.* 
FROM tag_rel_messages trm 
INNER JOIN messages m ON (trm.message_id = m.message_id) 
INNER JOIN tag_list tl ON (trm.tag_id=tl.tag_id 
WHERE tl.tag_name REGEXP 'pionas' AND tl.tag_name REGEXP 'website' 
GROUP By trm.message_id

But not display any records.

What's wrong with this query? Maybe i should use something other than REGEXP?

Thanks for help

I'm not sure how one column could match two things at the same time! You can use OR in place of AND , or you can use a single call to REGEXP .

SELECT m.* 
FROM tag_rel_messages trm 
INNER JOIN messages m ON (trm.message_id = m.message_id) 
INNER JOIN tag_list tl ON (trm.tag_id=tl.tag_id 
WHERE tl.tag_name REGEXP 'pionas|website' 
GROUP By trm.message_id

You need to join with the tag_list and tag_rel_message tables twice to match two different tags.

SELECT m.*
FROM messages AS m
JOIN tag_rel_messages AS trm1 ON m.message_id = trm1.message_id
JOIN tag_list AS t1 ON t1.tag_id = trm1.tag_id
JOIN tag_rel_messages AS trm2 ON m.message_id = trm2.message_id
JOIN tag_list AS t2 on t2.tag_id = trm2.tag_id
WHERE t1.tag_name = 'pionas' AND t2.tag_name = 'website'

Another way to do it is to join with either tag, and count the number of results per message

SELECT m.*
FROM messages AS m
JOIN tag_rel_messages AS trm ON m.message_id = trm.message_id
JOIN tag_list AS t ON t1.tag_id = trm.tag_id
WHERE t.tag_name IN ('pionas', 'website')
GROUP BY m.message_id
HAVING COUNT(*) = 2

This second form is a little easier to generalize to any number of tags. Put all the tags in the IN clause, and change the HAVING clause to match the number of tags.

$words = array('pionas', 'website');
$tags_id = array();
foreach ($words as $key => $val) {
    $sql = "SELECT tag_id FROM tag_list WHERE tag_name LIKE '%".$val."%'";
    $records = $db->query($sql);
    $tags_id[$key] = array_column($records, "tag_id");
}

$inner_array = array();
foreach ($tags_id as $k => $v) {
    $short_name = "trm_".$k;
    $inner_array[] = " INNER JOIN tag_rel_message as ".$short_name." ON ( ".$short_name.".message_id = m.message_id AND ".$short_name.".tag_id IN (".implode(", ", $v).")) ";
}

$sql = "SELECT DISTINCT m.* FROM messages m".implode(" ", $inner_array);

I think this is the same:

SELECT * FROM messages WHERE message_text like '%pionas%' AND message_text like '%website%'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM