2008-12-31 72 views
13

我需要使用全文搜索在數據庫中的兩個表中搜索多個列。所討論的兩個表格具有全文索引的相關列。在多個表中使用SQL Server 2008中的全文本搜索,列

的原因,我選擇了全文搜索: 1.爲了能夠方便地搜索重音字(CAFE) 2.爲了能夠根據字接近排名等 3.「難道你的意思是XXX?「功能

這裏是一個虛擬表結構,說明了這種挑戰:

 
Table Book 
BookID 
Name (Full-text indexed) 
Notes (Full-text indexed) 

Table Shelf 
ShelfID 
BookID 

Table ShelfAuthor 
AuthorID 
ShelfID 

Table Author 
AuthorID 
Name (Full-text indexed) 

我需要通過書名,書筆記和作者姓名進行搜索。

我知道有兩種方法來實現:

  1. 使用全文索引視圖:這將是我的首選方法,但我不能因爲一個視圖做到這一點要進行全文索引,它需要進行模式綁定,沒有任何外部連接,只有一個唯一的索引。我需要獲取數據的視圖不符合這些約束條件(它包含許多其他需要從中獲取數據的連接表)。

  2. 在存儲過程中使用聯接:這種方法的問題是我需要按排名排序結果。如果我在表中進行多個連接,默認情況下,SQL Server不會跨多個字段進行搜索。我可以在兩個鏈接的表上組合兩個單獨的CONTAINS查詢,但我不知道如何從兩個搜索查詢中提取合併的排名。例如,如果我搜索「亞瑟」,則應該考慮書籍查詢和作者查詢的結果並相應地加權。

+0

對於#1,你說你加入...你真的是外面加入?這是一個笛卡兒的產品,我懷疑你是否真的這樣做。內部或左/右連接很好。 – 2008-12-31 20:36:18

+0

我沒有爲任何顯示的表使用OUTER JOIN。還有其他我需要左外連接的表,因爲它們可能沒有任何FKed行。 – 2009-01-01 10:46:32

回答

14

使用FREETEXTTABLE,你只需要設計一些算法,計算出每個連接表的結果合併後的排名。下面的例子將結果從書本表中剔除。

SELECT b.Name, a.Name, bkt.[Rank] + akt.[Rank]/2 AS [Rank] 
FROM Book b 
INNER JOIN Author a ON b.AuthorID = a.AuthorID 
INNER JOIN FREETEXTTABLE(Book, Name, @criteria) bkt ON b.ContentID = bkt.[Key] 
LEFT JOIN FREETEXTTABLE(Author, Name, @criteria) akt ON a.AuthorID = akt.[Key] 
ORDER BY [Rank] DESC 

請注意,我簡化了這個例子的模式。

1

我會使用存儲過程。全文方法或任何返回一個排序,你可以排序。我不知道他們將如何加強對方,但我相信你可以修補一下並弄清楚。例如:

Select SearchResults.key, SearchResults.rank From FREETEXTTABLE(myColumn, *, @searchString) as SearchResults Order By SearchResults.rank Desc 
3

我不認爲接受的答案會解決問題。如果您嘗試查找某個作者的所有書籍,並因此將作者姓名(或部分作爲搜索條件)用作搜索條件,則查詢返回的唯一書籍將是那些具有自己名稱的搜索條件的書籍。

我看到這個問題的唯一方法是複製希望在Book表中搜索的作者列並索引這些列(或列,因爲將作者的相關信息存儲在XML中可能很明智Book表中的列)。

1

FWIW,在類似的情況我們DBA創建DML觸發器來維持一個專門的全文檢索表。由於存在很多限制,因此無法使用物化視圖。

3

我有同樣的問題,因爲你,但它實際上涉及10個表(一個用戶表和其他幾個人的信息)

我沒有WHERE子句中的每個表,但在查詢中使用FREETEXT我的第一個查詢取太長了。

我後來看到關於使用FREETEXTTABLE代替,並檢查在每個表的鍵列不是空值值幾個答覆,但也花了長期執行。

我固定它通過使用FREETEXTTABLE的組合和UNION選擇:

SELECT Users.* FROM Users INNER JOIN 
(SELECT Users.UserId FROM Users INNER JOIN FREETEXTTABLE(Users, (column1, column2), @variableWithSearchTerm) UsersFT ON Users.UserId = UsersFT.key 
UNION 
SELECT Table1.UserId FROM Table1 INNER JOIN FREETEXTTABLE(Table1, TextColumn, @variableWithSearchTerm) Table1FT ON Table1.UserId = Table1FT.key 
UNION 
SELECT Table2.UserId FROM Table2 INNER JOIN FREETEXTTABLE(Table2, TextColumn, @variableWithSearchTerm) Table2FT ON Table2.UserId = Table2FT.key 
... --same for all tables 
) fts ON Users.UserId = fts.UserId 

這被證明是令人難以置信的速度要快得多。

我希望它有幫助。

0

這個答案早就應該的,但要做到這一點,如果你不能修改主表的一種方法是創建一個新表增加一列的搜索參數。

然後創建該列全文索引和查詢該列。

SELECT 
    FT_TBL.[EANHotelID]     AS HotelID, 
    ISNULL(FT_TBL.[Name],'-')   AS HotelName, 
    ISNULL(FT_TBL.[Address1],'-')  AS HotelAddress, 
    ISNULL(FT_TBL.[City],'-')   AS HotelCity, 
    ISNULL(FT_TBL.[StateProvince],'-') AS HotelCountyState, 
    ISNULL(FT_TBL.[PostalCode],'-')  AS HotelPostZipCode, 
    ISNULL(FT_TBL.[Latitude],0.00)  AS HotelLatitude, 
    ISNULL(FT_TBL.[Longitude],0.00)  AS HotelLongitude, 
    ISNULL(FT_TBL.[CheckInTime],'-') AS HotelCheckinTime, 
    ISNULL(FT_TBL.[CheckOutTime],'-') AS HotelCheckOutTime, 
    ISNULL(b.[CountryName],'-')   AS HotelCountry, 
    ISNULL(c.PropertyDescription,'-') AS HotelDescription, 
    KEY_TBL.RANK 

    FROM [EAN].[dbo].[tblactivepropertylist] AS FT_TBL INNER JOIN 
    CONTAINSTABLE ([EAN].[dbo].[tblEanFullTextSearch], FullTextSearchColumn, @s) 
     AS KEY_TBL 
    ON FT_TBL.EANHotelID = KEY_TBL.[KEY] 
    INNER JOIN [EAN].[dbo].[tblCountrylist] b 
    ON FT_TBL.Country = b.CountryCode 
    INNER JOIN [EAN].[dbo].[tblPropertyDescriptionList] c 
    ON FT_TBL.[EANHotelID] = c.EANHotelID 

在上述[EAN]的代碼。[DBO]。[tblEanFullTextSearch],FullTextSearchColumn是新的表並用的字段添加的列,你現在可以做在一個查詢新的表格連接到要顯示數據的表格。

希望這會有幫助

相關問題