Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 我可以查询SQL Server';词干?_Sql Server_Stored Procedures - Fatal编程技术网

Sql server 我可以查询SQL Server';词干?

Sql server 我可以查询SQL Server';词干?,sql-server,stored-procedures,Sql Server,Stored Procedures,我知道我可以运行类似于以下的搜索来查找包含同一单词的多种形式的行(例如“hammers”): 是否可以编写一个存储过程(或以其他方式获取单词的词根,最好具有MSSQL将返回的相同结果),使给定的任何形式的单词只返回该单词的词根?(例如,“hammer”代表“hammers”,或“goose”代表“geese”)我认为答案是否定的。你需要有一个单词库,词根等等。例如,你需要提供以下信息:“monk”和“monkey”是否有相同的词根?我建议你读一读 也许这对你合适 SET @currentWord

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


是否可以编写一个存储过程(或以其他方式获取单词的词根,最好具有MSSQL将返回的相同结果),使给定的任何形式的单词只返回该单词的词根?(例如,“hammer”代表“hammers”,或“goose”代表“geese”)

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

也许这对你合适

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


我仍在制定细节,但目前有一个部分解决方案:

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

  • 存储的过程使用fn_Split将输入列表(例如,
    'dog,dogs,cat,cats'
    )拆分为一个表变量,然后将其插入永久表(需要在
    word
    列上获取全文索引)

  • 然后,它使用
    FORMSOF(屈折,…)
    search循环表中的内容,并标记所有相关的词(包括将搜索词与自身匹配)

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

存储过程存在一个问题(稍后将详细介绍);但到目前为止,我的程序如下:

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
虽然这并没有解决我最初的目标,即获取输入单词的词干,但它确实解决了我在报告中对同一单词的多种形式进行分组的迫切需要

问题是:

第一次运行该过程时,它将返回associatedWordId列的所有
null
值。如果我立即重新运行它,就会得到所需的输出。我猜这和索引创建的时间有关。在填充永久表(
tblWordAssociation
)之后,但在开始循环之前,我尝试添加一个
select*
,但没有解决问题

我尝试将存储的过程拆分为两个:一个用于删除/插入,另一个用于更新+选择。当连续快速运行时,这并没有解决问题;但是,如果我在运行它们之间短暂停顿,结果与预期的一样。我认为这表明指数需要一定的时间来建立。因此,我认为唯一合乎逻辑的做法是让我的应用程序扫描第二个进程的结果以查找空值,如果找到空值,请等待几秒钟,然后重试


有没有办法让我的进程等待索引生成后再继续?

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

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

或者,也可以使用API或其他服务来确定根单词。我注册并开始尝试,但不幸的是,它在规范化方面做得很差。它有“猫”->“猫”,但没有“鹅”->“鹅”,甚至没有“人”->“人”。我的最终目标是收集文章中出现的单词数据集(例如,人、人、人、人),并对它们进行汇总,这样我们就可以看到词根(“人”)出现357次,它是具有相同词根的所有单词出现次数的集合。我将尝试使用soundex函数(SQL之外),但我不希望它能满足我的需要。正如我所怀疑的,soundex似乎不是我需要的答案。下面是我的示例单词的soundex值:human=H550,humans=H552,humany=H552,humanity=H553。即使将其拆分为两个存储过程也不能解决(我认为)索引计时问题,但它确实允许我按照以下思路执行:
while(isNull(resultset)){sleep(10);getResultSet();}}
无需每次重新插入数据。就目前而言,我正在使用它,它的工作正如预期的那样。
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
SELECT * FROM sys.dm_fts_parser('FORMSOF(INFLECTIONAL, "dogs")', 1033, NULL, 1)