我有一个专有名称列表(在一个表中),以及另一个带有自由文本字段的表。我想检查该字段是否包含任何适当的名称。如果只有一个,我可以做
WHERE free_text LIKE "%proper_name%"
但是您如何针对整个列表执行此操作?我可以在列表中使用更好的字符串功能吗?
谢谢
答案 0 :(得分:0)
否,like
没有该功能。
许多数据库支持正则表达式,使您可以执行所需的操作。例如,在Postgres中,其表达为:
where free_text ~ 'name1|name2|name3'
许多数据库还具有全文搜索功能,可以加快此类搜索的速度。
这两种功能都是针对您所使用的数据库的。
答案 1 :(得分:0)
好吧,您可以在标准LIKE
中使用JOIN
,但是查询很可能会很慢,因为它将搜索每个free_text
中的每个专有名称。
例如,如果列表中有10个专有名称,并且某个free_text
值包含名字,则服务器将继续处理其余9个名称。
以下是查询:
SELECT -- DISTINCT
free_text_table.*
FROM
free_text_table
INNER JOIN proper_names_table ON free_text_table.free_text LIKE proper_names_table.proper_name
;
如果某个free_text
值包含多个专有名称,则该行将返回多次,因此您可能需要向查询中添加DISTINCT
。这取决于您的需求。
可以使用LATERAL JOIN
来避免笛卡尔积(将free_text_table
中的每一行与proper_names_table
中的每一行进行比较)。最终结果可能比简单变体更快。这取决于您的数据分布。
这是SQL Server语法。
SELECT
free_text_table.*
FROM
free_text_table
CROSS APPLY
(
SELECT TOP(1)
proper_names_table.proper_name
FROM proper_names_table
WHERE free_text_table.free_text LIKE proper_names_table.proper_name
-- ORDER BY proper_names_table.frequency
) AS A
;
这里我们不需要DISTINCT
,结果free_text_table
中的每一行中最多会有一行(一或零)。由于有proper_names_table
子句,发现第一个匹配项后,Optimizer应该足够聪明,可以停止读取和处理TOP(1)
。
如果您还可以以某种方式排序您的专有名称并将最有可能找到的专有名称放在首位,那么查询比简单的JOIN
更有可能更快。 (在子查询中添加一个合适的ORDER BY
子句)。