2011-09-01 58 views
1

我有一个表格,其中有一个列为nvarchar(max),其中的文字从文档中提取。我怎样才能创建一个选择查询,我会传递另一个关键字列表作为参数,并返回按匹配数量排序的行?用于匹配关键字的SQL查询?

也许这是可能与全文搜索?

+2

你试过什么了吗? – msarchet

+0

是的...我选择所有的行,并在C#中手动执行...生产系统非常慢 – Gustav

+0

@Gustav你能展示你在C#中尝试过什么吗? – reggie

回答

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 

然后你可以通过@List(例如来自C#的文件编号为EXEC dbo.Search @List = N'foo,bar,splunge')。

这会不会是超级快,但我敢肯定,这将是比所有的数据拉出到C#和双嵌套循环它手动更快。

+0

谢谢!但那是什么UpperLimit? – Gustav

+0

您希望传递给@List的最长字符串的长度。或者您希望用于其他目的的最大数量(Numbers表对于许多功能非常方便 - 请参阅http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-numbers- table.html)。如果不清楚,请不要在每次运行查询时创建Numbers表 - Numbers表和函数只应创建一次。 –

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,它有两个输入,并返回一个整数:大textvalue是第一个输入和字Y你在寻找一个逗号分隔的字符串是第二个。该函数返回一个整数,表示不同的查找单词,这些单词在文本中至少发现一次,或查找单词的总次数。实施 - 如何减肥 - 取决于你。例如,你可能希望按照最重要或最不重要的顺序来排列所查找的单词,并且让一个重要的单词比一个不太重要的单词更重要。

然后,您可以使用您的全文搜索引擎来查找包含的话至少一个(你会或它们)的所有记录,而你运行这个结果,通过你的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