18

我需要使用全文搜索从我的数据库中的两个表中搜索多个列。有问题的两个表已对相关列进行了全文索引。

我选择全文搜索的原因: 1. 能够轻松搜索带重音的单词(cafè) 2. 能够根据单词接近度等进行排名 3. “您是说 XXX 吗?” 功能性

这是一个虚拟表结构,用于说明挑战:

表书
书号
名称(全文索引)
注释(全文索引)

桌架
货架编号
书号

桌架作者
作者ID
货架编号

表作者
作者ID
名称(全文索引)

我需要搜索书名、书注和作者姓名。

我知道有两种方法可以做到这一点:

  1. 使用全文索引视图:这本来是我的首选方法,但我不能这样做,因为要对视图进行全文索引,它需要是模式绑定的,没有任何外部连接,有唯一的索引. 我需要获取数据的视图不满足这些约束(它包含我需要从中获取数据的许多其他连接表)。

  2. 在存储过程中使用连接:这种方法的问题是我需要按等级对结果进行排序。如果我跨表进行多个连接,默认情况下 SQL Server 不会搜索多个字段。我可以在两个链接表上组合两个单独的 CONTAINS 查询,但我不知道如何从两个搜索查询中提取组合排名。例如,如果我搜索“Arthur”,则应考虑 Book 查询和 Author 查询的结果并相应地加权。

4

6 回答 6

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

请注意,我为此示例简化了您的架构。

于 2008-12-31T18:24:27.777 回答
6

我和你有同样的问题,但它实际上涉及 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

事实证明,这快得令人难以置信。

我希望它有所帮助。

于 2016-08-08T16:05:09.347 回答
4

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

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

于 2009-08-27T19:31:55.487 回答
3

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

于 2011-02-19T18:04:17.210 回答
1

我会使用存储过程。全文方法或任何返回您可以排序的排名。我不确定它们将如何相互权衡,但我相信你可以修补一段时间并弄清楚。例如:

Select SearchResults.key, SearchResults.rank From FREETEXTTABLE(myColumn, *, @searchString) as SearchResults Order By SearchResults.rank Desc
于 2008-12-31T18:15:22.240 回答
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 是添加了字段的新表和列,您现在可以通过连接到要显示数据的表对新表进行查询.

希望这可以帮助

于 2016-12-30T23:51:51.203 回答