我可以查询SQL Server的词干吗?

时间:2011-02-22 15:20:20

标签: sql-server stored-procedures

我知道我可以运行类似下面的搜索来查找包含同一单词的多种形式的行(例如“锤子”):

SET @currentWord = 'hammers'
SET @stemSearch = 'FORMSOF(INFLECTIONAL,' + @currentWord + ')'
SELECT @matches = count(word) FROM tblWord WHERE CONTAINS(word, @stemSearch)

是否有可能编写一个存储过程(或以其他方式得到该词的根,最好具有与MSSQL相同的结果),给定任何形式的单词将只返回该单词的根? (例如“锤子”用于“锤子”,或“鹅”用于“鹅”)

3 个答案:

答案 0 :(得分:1)

我认为答案是肯定的。你需要有一个单词库,它们的根等等。例如,你需要提供以下信息:'monk'和'monkey'是否具有相同的根?我建议阅读SOUNDEX

也许这会为你做的

SET @currentWord = 'hammers'
SET @stemSearch = 'FORMSOF(INFLECTIONAL,' + @currentWord + ')'
SELECT @matches = count(word) FROM tblWord WHERE SOUNDEX(word)=SOUNDEX(@stemSearch)

SET @currentWord = 'hammers'
SET @stemSearch = 'FORMSOF(INFLECTIONAL,' + @currentWord + ')'
SELECT @matches = count(word) FROM tblWord WHERE DIFFERENCE(word, @stemSearch) IN (4,3)

答案 1 :(得分:1)

我仍在研究细节,但现在这是一个部分解决方案:

  • 我创建了一个表和一个将用于此目的的存储过程。该表有一个代理键,一个名为word的列和一个名为associatedWordId的列。

  • 存储过程使用fn_Split将输入列表(例如'dog,dogs,cat,cats')拆分为表变量,然后将它们插入到永久表中(需要在{{1}上获取全文索引) }专栏)。

  • 然后使用word搜索循环遍历表格内容,并标记所有相关字词(包括将搜索字词与自身匹配)。

  • 然后,我可以查询结果表格,将我的报告数据分组为同一个单词的多种形式。

存储过程存在一个问题(稍后会详细介绍);但到目前为止这是我的过程:

FORMSOF(INFLECTIONAL, ...)

虽然这并没有解决我最初获得输入词干的目标,但它确实解决了我在报告中对同一个词的多种形式进行分组的迫切需要。

这就是问题:

第一次运行proc时,它会返回associatedWordId列的所有CREATE PROCEDURE [dbo].[usp_identifyWordAssociations] ( @words varchar(max) ) AS --clear out the existing data delete from tblWordAssociation --insert the new words insert into tblWordAssociation (word) select [value] from fn_splitList(@words) --get a copy to loop from create table #myTmpTable ( word varchar(100) ) insert into #myTmpTable select word from tblWordAssociation --loop over each word declare @word varchar(100), @wordId int, @wordParent int, @stemSearch varchar(120) while exists (select top 1 word from #myTmpTable) begin select top 1 @word = word from #myTmpTable --get the word information select top 1 @wordId = id, @wordParent = associatedWordId from tblWordAssociation where word = @word --if the word hasn't already been looked up if (@wordParent is null) begin --setup stem search set @stemSearch = 'FORMSOF(INFLECTIONAL,' + @word + ')' --update all other forms of the current word with this word update tblWordAssociation set associatedWordId = @wordId where id in ( --get words that are other forms of the current word select id from tblWordAssociation where contains (word, @stemSearch) and associatedWordId is null ) end --now that we're done with this word, remove it from the temp table delete from #myTmpTable where word = @word end drop table #myTmpTable select id, word, associatedWordId from tblWordAssociation GO 值。如果我然后立即重新运行它,我得到所需的输出。我猜这与索引创建的时间有关。我在填充永久表(null)之后但在开始循环之前尝试添加select *,但是没有解决它。

我尝试将存储过程拆分为两个:一个用于删除/插入,另一个用于更新+选择。当快速连续运行时,这并没有解决问题;但是,如果我在运行它们之间暂停一下,结果就像预期的那样。我相信这表明索引需要一定的时间来构建。因此,我能想到的唯一合乎逻辑的事情是让我的应用程序扫描第二个proc的结果为NULL,如果找到,请等待几秒钟再试一次。

有没有办法让我的proc等到构建索引之后再继续?

答案 2 :(得分:0)

是的,您可以获得SQL Server在CONTAINS查询中使用的相同屈折表单。可以使用以下函数直接调用SQL Server FTS解析器,此函数可以使用CONTAINS中使用的任何谓词:

SELECT * FROM sys.dm_fts_parser('FORMSOF(INFLECTIONAL, "dogs")', 1033, NULL, 1)