在SQL Server 2008中跨多个表,列使用全文搜索

时间:2008-12-31 17:57:24

标签: sql-server sql-server-2008 full-text-search

我需要使用全文搜索在我的数据库中的两个表中搜索多个列。有问题的两个表都有相关的全文索引列。

我选择全文搜索的原因: 1.能够轻松搜索重音词(cafè) 2.能够根据单词接近度等排名 “你的意思是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查询,但我不知道从两个搜索查询中提取组合排名的方法。例如,如果我搜索“Arthur”,则应考虑Book查询和Author查询的结果并相应地加权。

6 个答案:

答案 0 :(得分:15)

使用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 :(得分:5)

我遇到了和你一样的问题,但它实际上涉及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

事实证明这要快得多。

我希望它有所帮助。

答案 2 :(得分:3)

我认为接受的答案不会解决问题。如果您尝试查找某位作者的所有书籍,并因此使用作者的姓名(或其中的一部分)作为搜索条件,则查询返回的唯一书籍将是具有自己名称的搜索条件的书籍。

我看到这个问题的唯一方法是复制您希望在Book表中搜索的作者列并索引这些列(或列,因为将作者的相关信息存储在XML列中可能很聪明在书表中。)

答案 3 :(得分:2)

FWIW,在类似的情况下,我们的DBA创建了DML触发器来维护专用的全文搜索表。由于其有许多限制,因此无法使用物化视图。

答案 4 :(得分:1)

我会使用存储过程。全文方法或其他任何返回排序,您可以排序。我不确定他们将如何对抗彼此,但我相信你可能会修补一段时间并弄清楚。例如:

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

答案 5 :(得分: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是添加了字段的新表和列,现在可以对新表进行查询,并连接到要显示的表来自的数据。

希望这有帮助