【问题标题】:MySQL - alternative for like - regexp?MySQL - like 的替代品 - 正则表达式?
【发布时间】:2015-12-21 19:47:43
【问题描述】:

我的数据库表中有超过一百万条记录。 当我使用 like 时速度很慢,当我使用 ma​​tch against 时,他们丢失了一些记录。

我创建帮助表:

tag_list

tag_id
tag_name

tag_rel_message

tag_id
messag_id

消息

message_id
message_text

在 tag_list 中我添加了 $message_text 的所有单词 - explode(" ", $message_text);

我的新查询是:

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

但不显示任何记录。

这个查询有什么问题? 也许我应该使用 REGEXP 以外的东西?

感谢您的帮助

【问题讨论】:

  • 如果我理解正确的话,tag_list 的tag_name 只包含单个token 关键字,那么任何单个token 怎么可能同时匹配pionaswebsite
  • 是的,只有单个关键字。你是对的。那么我应该怎么做才能只找到所有条件都为真的这条消息?
  • 您的WHERE 子句指出tag_name 需要同时匹配'pionas' AND 'website'。也许尝试OR 而不是AND
  • 为什么是LIKEREGEXP?为什么不tag_name = 'pionas'
  • 我使用正则表达式,因为 tag_name 可能是网站、网站等

标签: mysql regex


【解决方案1】:

我不确定一列如何同时匹配两件事!您可以使用OR 代替AND,或者您可以使用单个调用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

【讨论】:

    【解决方案2】:

    您需要加入tag_listtag_rel_message 表两次以匹配两个不同的标签。

    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'
    

    另一种方法是加入任一标签,并计算每条消息的结果数

    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
    

    第二种形式更容易推广到任意数量的标签。将所有标签放在IN 子句中,并更改HAVING 子句以匹配标签数量。

    【讨论】:

      【解决方案3】:
      $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);
      

      我认为是一样的:

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

      【讨论】:

        猜你喜欢
        • 2010-10-05
        • 1970-01-01
        • 2011-10-06
        • 1970-01-01
        • 1970-01-01
        • 2020-06-05
        • 1970-01-01
        • 2017-11-21
        • 1970-01-01
        相关资源
        最近更新 更多