2010-01-14 58 views
1

我目前正在開發一個項目,我只想通過一個輸入搜索詞搜索員工。爲此,我使用SQL FTS。SQL Server全文搜索 - 創建一個計算列

表架構看起來像這樣

Employee表

僱員,名字,姓氏

的樣本數據

1,約翰·米勒

2, Chuck,Norris


地址表

AddressId,僱員,CityId,街道,StreetNumber

樣本數據

1,1,1,大街,12

2 ,2,溫布爾登路2號,12號


市臺

CityId,姓名,郵編

的樣本數據

1,漢堡,22335

2,倫敦,12345


所以,現在我得到了以下搜索詞:

  • 約翰漢堡:指約翰和漢堡,並應返回1個記錄。
  • 約翰倫敦:意味着約翰和倫敦,應該返回0條記錄,因爲在倫敦沒有約翰。
  • Norris Wimbledon:意思是Norris和Wimbledone,應該返回1條記錄。

現在的問題是,使用CONTAINSTABLE只允許一次搜索一個表。因此,在「員工全文」目錄中應用「John AND Hamburg」,因爲「漢堡」位於地址表中,所以返回0個記錄。

所以目前我可以用「OR」,而不是「與」唯一,如:

SELECT 
    (keyTblSp.RANK * 3) AS [Rank], 
    sp.* 
FROM Employee sp  
    INNER JOIN 
     CONTAINSTABLE(Employee, *, 'John OR Hamburg', 1000) AS keyTblSp 
     ON sp.EmployeeId = keyTblSp.[KEY]  

UNION ALL 
SELECT 
    (keyTbl.RANK * 2) AS [Rank], 
    sp.* 
FROM Employee sp  
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId 
    INNER JOIN 
     CONTAINSTABLE([Address], *, 'John OR Hamburg', 1000) AS keyTbl 
     ON addr.AddressId = keyTbl.[KEY]  
UNION ALL 
SELECT 
    (keyTbl.RANK * 2) AS [Rank], 
    sp.* 
FROM Employee sp  
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId 
    LEFT OUTER JOIN [City] cty ON cty.CityId = addr.CityId 
    INNER JOIN 
     CONTAINSTABLE([City], *, 'John OR Hamburg', 1000) AS keyTbl 
     ON cty.CityId = keyTbl.[KEY] 

這會導致不只是約翰誰住漢堡返回,但每一個名爲約翰和每個人的人誰住在漢堡。 我能想到的一個解決方案是以某種方式計算員工表中的一列,其中包含全文搜索的所有必要值。

Employee表

EMPLOYEEID,名字,姓氏,FulltextColumn

樣本數據

1 |約翰|米勒| 約翰·米勒大道12漢堡22335

於是我可以做

SELECT 
    (keyTbl.RANK) AS [Rank], 
    sp.* 
FROM Employee sp  
    INNER JOIN 
     CONTAINSTABLE([Employee], FulltextColumn, 'John AND Hamburg', 1000) AS keyTbl 
     ON sp.EmployeeId = keyTbl.[KEY] 

這可能嗎?任何其他想法?

回答

1

您可以使用連接來要求地址和人員名稱都匹配。

SELECT 
    (keyTblSp.RANK * 3) AS [Rank], 
    sp.* 
FROM Employee sp  
    INNER JOIN 
     CONTAINSTABLE(Employee, *, 'John OR Hamburg', 1000) AS keyTblSp 
     ON sp.EmployeeId = keyTblSp.[KEY]  
join 
(
    SELECT 
     (keyTbl.RANK * 2) AS [Rank], 
     sp.* 
    FROM Employee sp  
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId 
    INNER JOIN 
     CONTAINSTABLE([Address], *, 'John OR Hamburg', 1000) AS keyTbl 
     ON addr.AddressId = keyTbl.[KEY] 
UNION ALL 
    SELECT 
     (keyTbl.RANK * 2) AS [Rank], 
     sp.* 
    FROM Employee sp  
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId 
    LEFT OUTER JOIN [City] cty ON cty.CityId = addr.CityId 
    INNER JOIN 
     CONTAINSTABLE([City], *, 'John OR Hamburg', 1000) AS keyTbl 
     ON cty.CityId = keyTbl.[KEY] 
) addr_matches 
on addr_matches.EmployeeId = sp.EmployeeId 

,我認爲會給你你指定的,但是很明顯,這需要雙方的名稱和搜索返回任何結果的地址搜索詞的結果。你沒有說明如果有人只是搜索'約翰',如果你總是會得到一個姓名和地址,會發生什麼事情,我認爲上述將工作正常。

0

我認爲計算列是你最好的選擇。這將是最靈活的,因爲您不知道哪些令牌會出現在搜索查詢中,它會更好地執行,並且您的存儲過程會更小。

爲了創建基於另一個表中數據計算列,你將有使用UDF(用戶定義函數)這樣的創造:

CREATE FUNCTION dbo.udf_ComputedColumnFunction (
    @EmployeeId INT 
) 
RETURNS VARCHAR(1000) 
AS 
BEGIN 
    DECLARE @RET VARCHAR(1000) 

    SELECT 
     @RET = e.FirstName + ' ' + e.LastName + ' ' + a.Street + ' ' + a.StreetNumber + ' ' + c.Name + ' ' + c.ZipCode 
    FROM Employee e 
    INNER JOIN Address a ON a.EmployeeId = e.EmployeeId 
    INNER JOIN City c ON c.CityId = a.CityId 

    RETURN @RET 
END 
GO 


ALTER TABLE Employee 
ADD SearchColumn AS dbo.udf_ComputedColumnFunction(EmployeeId) 

如果你不想做那麼,您可以:

  • 創建一個indexed view並將FullText索引添加到該索引上。
  • 創建由觸發器填充的查找表或定期運行存儲過程。
+0

嗨,謝謝你的建議。我知道有一張特殊的表格,其中包含了所有必要的信息。存儲過程用於通過爲每個參與表使用觸發器來更新索引。全文目錄用於新表執行快速搜索。 – Chris 2010-01-20 10:19:35

0

我想你應該創建和索引視圖,並應加入哪個可以全文通過與空格或破折號分開使用在一個單柱要組合的所有列,因爲它們都是用於SQL Server 2005的噪音詞然後在該索引視圖中創建一個全文索引。

包含表格默認情況下不應用FormsOf折點或形式的同義詞庫。這兩個是配置和使用的好選擇。

如果您只想使用「OR」,那麼使用FreeTextTable就好像默認情況下同時應用Forms of the Forms和FormsOf inflectional一樣。