【问题标题】:MySQL: dynamic "IN" clause from a split on a stringMySQL:来自字符串拆分的动态“IN”子句
【发布时间】:2026-01-08 23:15:02
【问题描述】:

我有一个表格“wordlist”,每个单词都有一个分数:1 或 -1:

id | name | val
1, 'hello', 1,
2, 'world', -1
3, 'test', 1,
...

我还有一个包含文本的表格“文本”:

id | text | score
1, 'hello world', 0
2, 'Lorem Ipsum Dolor Sit Amet...', 0
...

我想用这条规则更新表“文本”中的“分数”字段:

score = sum(wordlist.val) 其中句子的每个单词都出现在单词列表中。

我试过这种方法,但它不起作用:

update texts as t set score=(select sum(val) from wordlist where word in (concat('\'', replace(t.text,' ','\',\''),'\'')))

我有超过 50 万行数据要处理,所以我宁愿只使用 MySQL,而不使用任何 PHP。

如果您有解决方案,请提前致谢!

我希望 MySQL 中有一个 explode() 函数!

【问题讨论】:

    标签: mysql dynamic split explode


    【解决方案1】:

    你可以像这样使用 FIND_IN_SET():

    select
      texts.*, sum(val)
    from
      texts left join wordlist
      on find_in_set(wordlist.name, replace(texts.`text`, ' ', ','))>0
    group by texts.id
    

    如果你需要更新你的表格,你可以使用这个:

    update texts inner join (
      select texts.id, sum(val) as score
      from texts left join wordlist
           on find_in_set(wordlist.name, replace(texts.`text`, ' ', ','))>0
      group by texts.id) s
      on texts.id=s.id
    set texts.score=s.score
    

    【讨论】:

    • 很好,find_in_set() 应该很快!不过可能需要group by
    • @ebyrob 是的,我忘记了分组,抱歉 :) find_in_set 很好,但我不认为它比 like
    【解决方案2】:

    您可以使用RLIKE 进行带有单词边界的正则表达式匹配,如下所示:

    UPDATE texts SET score = text_scores.score
    FROM (
      SELECT texts.id as text_id, SUM(wordlist.val) as score
      FROM texts
      JOIN wordlist
        ON texts.text RLIKE CONCAT('[[:<:]]', wordlist.name, '[[:>:]]')
      GROUP BY texts.id) text_scores
    WHERE id = text_scores.text_id
    

    【讨论】:

    • 可能也适用于常规,例如:ON CONCAT(' ', texts.text, ' ') LIKE CONCAT('% ', wordlist.name, ' %')