2011-09-01 27 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