SQL在文本字段中选择包含子字符串的行

Posted

技术标签:

【中文标题】SQL在文本字段中选择包含子字符串的行【英文标题】:SQL select rows containing substring in text field 【发布时间】:2014-02-17 15:01:27 【问题描述】:

我在 Postgresql 数据库中有 CLIENTS_WORDS 表,其中包含以下列:ID、CLIENT_ID、WORD

ID|CLIENT_ID|WORD
1 |1242     |word1
2 |1242     |WordX.foo
3 |1372     |nextword
4 |1999     |word1

在此表中可能有大约 100k-500k 行。 我有这样的查询字符串:

'Some people tell word1 to someone'
'Another stringWordX.foo too possible'

我希望从查询字符串中包含 WORD 列文本的表中选择 *。 现在我使用选择

select * from CLIENTS_WORDS
where strpos('Some people tell word1 to someone', WORD) > 0

我的问题,检索匹配行的最佳性能/快速方法在哪里?

【问题讨论】:

小写/大写重要吗?您的 Postgres 版本是什么? 忽略大小写,postgres 9.3 最新 【参考方案1】:

使用unnest() 和 JOIN 可以获得更好的性能。像这样:

SELECT DISTINCT c.client_id
FROM   unnest(string_to_array('Some people tell word1 ...', ' ')) AS t(word)
JOIN   clients_words c USING (word);

查询的详细信息取决于缺少的需求详细信息。这是在 space 个字符处拆分字符串。

更灵活的工具是regexp_split_to_table(),您可以在其中使用character classes or shorthands 作为分隔符。喜欢:

regexp_split_to_table('Some people tell word1 to someone', '\s') AS t(word)
regexp_split_to_table('Some people tell word1 to someone', '\W') AS t(word)
相关回答:Django. PostgreSQL. regexp_split_to_table not working A search for more answers for regular expression class shorthands.

当然,clients_words.word 列需要为性能建立索引:

CREATE INDEX clients_words_word_idx ON clients_words (word)

会很快。

忽略单词边界

如果您想完全忽略单词边界,那么整个问题就会变得更加昂贵。 LIKE / ILIKE 结合三元组 GIN 索引会浮现在脑海中。详情看这里:PostgreSQL LIKE query performance variations

或其他模式匹配技术 - 在 dba.SE 上回答:Pattern matching with LIKE, SIMILAR TO or regular expressions in PostgreSQL

但是,您的情况倒退,索引不会有帮助。您必须检查每一行是否有部分匹配 - 使查询非常昂贵。更好的方法是 reverse 操作:拆分单词并然后搜索。

【讨论】:

如果可搜索的单词可以用 ' ' 空格分隔,但如果尝试 'Another stringWordX.foo too possible' 将不匹配 WordX.foo,则它的工作原理 @Dmitry:我添加了更多关于正则表达式和模式匹配的内容。

以上是关于SQL在文本字段中选择包含子字符串的行的主要内容,如果未能解决你的问题,请参考以下文章

sql 从文本字段中选择子字符串

如何使用 T-SQL 在数据库中的所有文本字段中搜索某些子字符串

Pandas:从列表中选择包含任何子字符串的行

在另一个字段Oracle SQL中包含的一个字段中查找文本

SQL Regex - 用另一个字段的子字符串替换

替换数据库文本字段中所有出现的子字符串