用于匹配关键字的SQL查询?

时间:2011-09-01 18:05:39

标签: sql sql-server-2008 full-text-search

我有一个列为nvarchar(max)的表格,其中包含从word文档中提取的文本。如何创建一个选择查询,我将另一个关键字列表作为参数传递,并返回按匹配数排序的行?

使用全文搜索可能有可能吗?

2 个答案:

答案 0 :(得分:1)

是的,可以使用全文搜索,可能是最好的答案。对于直接的T-SQL解决方案,您可以使用拆分功能并加入,例如假设一个名为dbo.Numbers的数字表(您可能需要决定不同的上限):

SET NOCOUNT ON;
DECLARE @UpperLimit INT;
SET @UpperLimit = 200000;

WITH n AS
(
    SELECT
        rn = ROW_NUMBER() OVER
        (ORDER BY s1.[object_id])
    FROM sys.objects AS s1
    CROSS JOIN sys.objects AS s2
    CROSS JOIN sys.objects AS s3
)
SELECT [Number] = rn - 1
INTO dbo.Numbers
FROM n
WHERE rn <= @UpperLimit + 1;

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers([Number]);

使用该数字表的分裂函数:

CREATE FUNCTION dbo.SplitStrings
(
    @List NVARCHAR(MAX)
)
RETURNS TABLE
AS
    RETURN
    (
        SELECT DISTINCT
            [Value] = LTRIM(RTRIM(
                SUBSTRING(@List, [Number],
                CHARINDEX(N',', @List + N',', [Number]) - [Number])))
        FROM
            dbo.Numbers
        WHERE
            Number <= LEN(@List)
            AND SUBSTRING(N',' + @List, [Number], 1) = N','
    );
GO

然后你可以简单地说:

SELECT key, NvarcharColumn /*, other cols */
FROM dbo.table AS outerT
WHERE EXISTS
(
  SELECT 1 
    FROM dbo.table AS t 
    INNER JOIN dbo.SplitStrings(N'list,of,words') AS s
    ON t.NvarcharColumn LIKE '%' + s.Item + '%'
    WHERE t.key = outerT.key
);

作为程序:

CREATE PROCEDURE dbo.Search
    @List NVARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT key, NvarcharColumn /*, other cols */
    FROM dbo.table AS outerT
    WHERE EXISTS
    (
      SELECT 1 
        FROM dbo.table AS t 
        INNER JOIN dbo.SplitStrings(@List) AS s
        ON t.NvarcharColumn LIKE '%' + s.Item + '%'
        WHERE t.key = outerT.key
    );
END
GO

然后您可以从C#传入@List(例如EXEC dbo.Search @List = N'foo,bar,splunge')。

这不会超快,但我确信它会比将所有数据拉入C#并手动双嵌套循环更快。

答案 1 :(得分:0)

how to ... return the rows ordered by the number of [full-text] matches

我自己没有使用它,但相信SQL Server 2008支持加权可能对您有帮助的CONTAINSTABLE匹配:

            http://msdn.microsoft.com/en-us/library/ms189760.aspx

如果您没有引擎返回按击中次数加权的结果......

你可以编写一个带有两个输入并返回一个整数的UDF:大文本值是第一个输入,你要查找的是逗号分隔的字符串是第二个。该函数返回一个整数,该整数表示在文本中至少实际找到一次的不同查找单词的数量,或者找到所查找单词的总次数。实施 - 如何减肥 - 取决于你。也许,例如,你想要在最重要到最不重要的顺序中安排所寻找的单词,并且给一个重要的单词比一个不太重要的单词命中更重要。

然后,您可以使用全文搜索引擎查找包含至少一个单词(您是OR)的所有记录,并通过UDF标量函数运行此结果集:

             pseudo code

            select title,  weightfunction(summary, 'word1,word2,word3....wordN')
            from docs
            where summary contains ( word1 or word2 or word3 ... or wordN)
            order by weightfunction(summary, 'word1,word2,word3....wordN') desc