我在这个问题上需要一些帮助:
作为输入,我有一个字符串,看起来像Blue cat green eyes 2342342
,或者它可以是Cat blue eyes green 23242
或任何其他字的排列。
在我的数据库表中,我有一些数据。其中一个专栏叫做keyWords。
以下是此表的示例:
我的任务是在我的数据库表格列KEYWORDS中找到记录,该列匹配输入字符串中的某些单词。
例如:对于字符串“蓝猫绿眼睛2342342” “猫蓝眼睛绿色23242”和“猫 23242眼睛蓝色绿色”结果必须是“蓝猫”(我桌子的第一行)。 我能想象如何解决这个任务的唯一方法是:
%like%
搜索每个单词。%like%
搜索此单词。此算法的图形架构为here
但是如果表中有很多记录并且我的输入字符串包含大量单词,那么看起来这个算法的工作速度会很慢。
所以,我的问题是:是否有任何特殊的算法可以帮助解决这个问题?
答案 0 :(得分:4)
您可以采用其他表格,例如
ID KeywordID Word
1 1 blue
2 2 blue
3 1 cat
并转换字符串
"Blue cat green eyes 2342342"
在一系列索引和计数中:
SELECT KeywordID, COUNT(*) FROM ancillary WHERE Word IN ('blue','cat','green','eyes'...)
这将执行一系列完全匹配并返回,例如
KeywordID Count
1 2
2 1
然后您知道ID为1的关键字组有两个单词,这意味着计数为2的所有单词都匹配。所以关键字1是满意的。第2组还有两个单词(黑色,猫),但只找到一个,但匹配在那里但不完整。
如果您还将关键字集大小与关键字ID一起记录,那么来自同一ID的所有关键字都将具有相同的KeywordSize,您也可以将它设为GROUP BY:
KeywordID KeywordSize Count
1 2 2
2 2 1
甚至可以SELECT COUNT(*)/KeywordSize AS match ... ORDER BY match
并按相关性排序关键字匹配。
当然,一旦你有KeywordID,你可以在关键字表中找到它。
您想要将关键字列表“black angry cat”添加到现有表格中。
因此,您将此关键字列表分解为单词:并获取“黑色”,“愤怒”和“猫”。
您通常会在已有的表中插入关键字列表,并检索新创建的行的ID,假设它是1701。
现在,您将这些单词插入到我们称之为“辅助”的新表中。此表仅包含主表的关键字行ID,单个单词以及该单词所来自的单词列表的大小。
我们知道我们总共插入3个单词,表格行1701,所以size = 3,我们插入这些元组:
(1701, 3, 'black')
(1701, 3, 'cat')
(1701, 3, 'angry')
(这些将获得他们自己的唯一ID,但这与我们无关。)
现在一段时间后我们会收到一句话,
'Schroedinger cat is black and angry'
我们可以首先针对要删除的空字列表运行查询,例如“is”和“and”。但这不是必要的。
然后我们可以运行与单词一样多的查询,从而发现没有任何行包含“Schroedinger”,我们可以放弃它。但这也没必要。
最后,我们针对辅助构建真正的查询:
SELECT KeywordID, COUNT(*) AS total, ListSize*100/COUNT(*) AS match
FROM ancillary WHERE Word IN ('Schroedinger','cat','is','black','and','angry')
GROUP BY KeywordID;
WHERE
会返回这些行:
(1234, 'black') -- from 'black cat'
(1234, 'cat') -- from 'black cat'
(1423, 'angry') -- from 'angry birds'
(1701, 'cat') -- from 'black angry cat'
(1701, 'angry') -- from 'black angry cat'
(1701, 'black') -- from 'black angry cat'
(1999, 'cat') -- from 'nice white cat'
因此,GROUP将返回这些行的KeywordID
及其基数:
1423 1 50%
1701 3 100%
1234 2 100%
1999 1 33%
现在你可以通过匹配比率降序排序,然后按列表大小降序排序(因为匹配3个单词的100%优于匹配2的100%,匹配1合2比3匹配2更好): / p>
1701 3 100% -- our best match
1234 2 100% -- second runner
1423 1 50%
1999 1 33%
您还可以在一个查询中检索第一个表格,并添加匹配率:
SELECT mytable.*, total, match FROM
mytable JOIN (
SELECT KeywordID, COUNT(*) AS total, ListSize*100/COUNT(*) AS match
FROM ancillary WHERE Word IN ('Schroedinger','cat','is','black','and','angry')
GROUP BY KeywordID
) AS ancil ON (mytable.KeywordID = ancil.KeywordID)
ORDER BY match DESC, total DESC;
最大的成本是“辅助”中的完全匹配,必须在Word
列上编制索引。
答案 1 :(得分:1)
你可能想看看全文搜索引擎,比如sphinx:http://sphinxsearch.com/
或者,另一种方法 - 创建存储过程,使用指定的分隔符将搜索字符串拆分为关键字,并查找数据库列中每个关键字的charindex(取决于您的数据库管理系统)