2008-11-21 33 views
6

目前我有一張表,我搜索4個字段,名字,姓氏,中間名和AKA的。我目前有一個CONTAINSTABLE搜索行,它的工作原理。不好,但它的作品。現在我想讓名字的權重更高一些,中間名較低。SQL Server Weighted Full Text Search

我找到了命令ISABOUT但似乎相當值錢,如果我有一句話不是列做到這一點(希望我理解這個錯誤)。這不是一個選項,如果它的話,因爲我不知道用戶將輸入多少字。

我發現線程here談論這個相同的解決方案,但我無法獲得接受的解決方案的工作。也許我做了一些錯誤的事情,但無論我不能工作,它的邏輯看起來真的很奇怪。必須有一個更簡單的方法。

回答

6

操縱排名的關鍵是使用聯合。對於每一列你使用一個單獨的select語句。在該語句中,添加一個標識符,該標識符顯示每行從哪個列被拉出。將結果插入到表變量中,然後可以通過對標識符進行排序操作排名,或者根據標識符將排名乘以某個值。

關鍵是給出修改排名的外觀,而不是實際改變sql server的排名。

例如使用表變量:

DECLARE @Results TABLE (PersonId Int, Rank Int, Source Int) 

對於列PersonId Int PK Identity, FirstName VarChar(100), MiddleName VarChar(100), LastName VarChar(100), AlsoKnown VarChar(100)每一列添加到全文目錄,您可以使用查詢表人物:

INSERT INTO @Results (PersonId, Rank, Source) 

SELECT PersonId, Rank, 1 
FROM ContainsTable(People, FirstName, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

UNION 
SELECT PersonId, Rank, 2 
FROM ContainsTable(People, MiddleName, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

UNION 
SELECT PersonId, Rank, 3 
FROM ContainsTable(People, LastName, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

UNION 
SELECT PersonId, Rank, 4 
FROM ContainsTable(People, AlsoKnown, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

/* 
Now that the results from above are in the @Results table, you can manipulate the 
rankings in one of several ways, the simplest is to pull the results ordered first by Source then by Rank. Of course you would probably join to the People table to pull the name fields. 
*/ 

SELECT PersonId 
FROM @Results 
ORDER BY Source, Rank DESC 

/* 
A more complex manipulation would use a statement to multiply the ranking by a value above 1 (to increase rank) or less than 1 (to lower rank), then return results based on the new rank. This provides more fine tuning, since I could make first name 10% higher and middle name 15% lower and leave last name and also known the original value. 
*/ 

SELECT PersonId, CASE Source WHEN 1 THEN Rank * 1.1 WHEN 2 THEN Rank * .9 ELSE Rank END AS NewRank FROM @Results 
ORDER BY NewRank DESC 

的一個缺點是你會注意到我沒有使用UNION ALL,所以如果一個單詞出現在多個列中,排名不會反映出來。如果這是個問題,您可以使用UNION ALL,然後通過將全部或部分重複記錄的等級添加到具有相同人員ID的另一記錄的等級中,刪除重複的人員ID。

+0

這非常有幫助!這已經不是SQL Server的內容了,這真是令人遺憾。 – 2011-02-27 19:54:42

2

級別在整個索引中無用,您無法合併它們並期望結果具有任何意義。每個指數的等級編號是沒有的相對含義的其他指標的WRT含量的蘋果/橙/葡萄/西瓜/對的比較。

當然,您可以嘗試鏈接/權重/排序索引之間的嘗試和結果有意義的結果,但在一天結束時,結果仍然是胡言亂語,但可能仍然足以提供一個可行的解決方案,具體取決於具體情況你的情況。

在我看來,最好的解決方案是將您希望搜索的所有數據放在一個FTS索引/列中,並使用該列排列您的輸出。即使您必須複製字段內容以完成結果。

0

我認爲返回的數據會加入到模式中的其他表中?我會根據從關聯數據到全文索引的列開發自己的RANK。這也爲RANK值提供了保證的準確度。

2

就在幾周前,我正在解決非常類似的問題,解決方案非常容易(儘管醜陋和空間消耗)。 按此順序再創建一個包含FirstName + FirstName + LastName + MiddleName的組合值的列。重複的名字列是不是排字錯誤,這是一種伎倆,迫使FT在搜索過程中將來自FirstName的值加權得更高。

0

怎麼樣這樣:

SELECT p.* from Person p 
left join ContainsTable(Person, FirstName, @SearchValue) firstnamefilter on firstnamefiler.key = p.id 
left join ContainsTable(Person, MiddleName, @SearchValue) middlenamefilter on middlenamefilter.key = p.id 
where (firstnamefilter.rank is not null or middlenamefilter.rank is not null) 
order by firstnamefilter.rank desc, middlenamefilter.rank desc 

這將產生一個記錄每個Person記錄,其中第一或中間名(或兩者)上的搜索詞匹配,以及爲了通過對第一所有比賽(按降序排列),然後是所有匹配的中間名(再次按降序排列)