SQL WHERE使用LIKE并与字段进行比较

时间:2011-11-04 10:16:15

标签: mysql sql

我有这种情况:

我想查看特定的字词,如果它们匹配一个字词,我将不得不更新该页面的内容并将其链接到该字词。但是现在我专注于获取内容页面,其中部分内容与特定术语相同。

这是我需要做的事情的想法,但它不起作用,因为子查询返回多个字段。

我想找到WHERE m.module_content类似于我所拥有的任何条款,但它应该全部检查。

SELECT m.module_termid, t.term_name, m.module_name, m.module_content
FROM modules m
JOIN terms t ON m.module_termid = t.term_id
WHERE m.module_content LIKE  '%' || (SELECT term_name FROM terms) ||  '%'

module_content包含html格式的文本,所以我最终需要做的是,如果它与一个术语匹配而且它还不是链接,我将添加一个指向该特定术语的链接。

这里最好的选择是什么? (我使用的是mysql btw)

为您举例说明预期结果:

条款:id:1,名称:hello 模块:id:1,内容:< p> Hello World< / p>

我想提出id为1的模块,因为它包含某个地方的名称为“hello”的内容

更新:

尝试过Pablo的解决方案,但这就是:

enter image description here

例如,“雷戴维斯”与“浮动”一词无关,所以不应该出现。

7 个答案:

答案 0 :(得分:5)

我认为您只需要将JOIN条件更改为:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  JOIN terms t ON (m.module_content LIKE  '%' || t.term_name ||  '%')

话虽如此,这可能是非常低效的。请考虑使用 FULL TEXT INDEX INSTEAD 进行此操作。

答案 1 :(得分:4)

经过一番研究,我的解决方案看起来像这样:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  INNER JOIN terms t ON m.module_termid = t.term_id
  WHERE m.module_content LIKE CONCAT('%', TRIM(t.term_name), '%')

编辑:关于Paul Morgans的评论,我将CONCAT('%', t.term_name, '%')替换为CONCAT('%', TRIM(t.term_name), '%'),以便删除t.term_name中的所有空格。如果您需要t.term_name中的空格,只需删除TRIM调用并使用旧版本(CONCAT('%', t.term_name, '%')

答案 2 :(得分:2)

MySQL没有任何连接运算符,查询实际应该写为:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  JOIN terms t ON m.module_content LIKE CONCAT('%', t.term_name, '%');

但是发生了什么:

m.module_content LIKE  '%' || t.term_name ||  '%'

实际上相当于

(m.module_content LIKE  '%') || (t.term_name) ||  ('%')

总是1.因此,你有一个笛卡儿积=)

UPD :作为对自己的引用,MySQL确实有一个连接运算符||,但要使用它,应该设置PIPES_AS_CONCAT模式:

mysql> SET sql_mode= 'pipes_as_concat';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT 'qwe' || 'asd';
+----------------+
| 'qwe' || 'asd' |
+----------------+
| qweasd         |
+----------------+
1 row in set (0.00 sec)

答案 3 :(得分:1)

您可以尝试这样做:

SELECT m.module_termid, t.term_name, m.module_name, m.module_content
  FROM modules m
  JOIN terms t ON (m.module_content LIKE  '%' + t.term_name +  '%')

答案 4 :(得分:1)

使用“IN”代替“LIKE”应该是解决方案:类似于: -

  

SELECT m.module_termid,t.term_name,m.module_name,m.module_content
    FROM modules m JOIN terms t ON m.module_termid = t.term_id
    在哪里m.module_content IN (SELECT term_name FROM terms);

答案 5 :(得分:0)

尝试以下查询 -

SELECT 
    tp.module_termid, 
    tp.term_name, 
    tp.module_name,
    tp.module_content  
FROM (
        SELECT 
            m.module_termid, 
            t.term_name, 
            m.module_name, 
            m.module_content,
            IF(LOCATE(t.term_name,m.module_content)!=0, m.module_content, ' ') 
                as required_content 
        FROM modules m 
        LEFT JOIN terms t ON m.module_termid = t.term_id
     ) tp 
WHERE tp.required_content != '';

对于上面的查询,您将获得模块表的module_content列中term_name列数据作为整个单词存在的所有行。如果你不想只对整个单词进行匹配,那么在这种情况下你可以使用MYSQL的正则表达式函数来代替LOCATE函数。

LOCATE 功能的文档可以在here

中找到

答案 6 :(得分:0)

我不认为这是一个解决问题的好方法,比如this.supports你有很多模块项,而且流行的词是limit.each你执行sql的时候,它需要大量的磁盘io并可能阻止在线mysql数据库。 我的方式是这样的:

  1. 反转索引模块内容。
  2. 使用索引搜索热门词汇。
  3. 将模块ID绑定到关键字。
  4. 正如你所看到的那样。它非常高效和快速。因此,问题是如何对模块内容进行反向索引。sphinx将做得很好。 希望这会对你有所帮助:)。