SQL Server全文搜索 - 对某些列加权

时间:2011-07-06 19:06:45

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

如果我有以下全文搜索查询:

SELECT *
FROM dbo.Product
   INNER JOIN CONTAINSTABLE(Product, (Name, Description, ProductType), 'model') ct
      ON ct.[Key] = Product.ProductID

是否可以称量正在搜索的列?

例如,我更关心出现在Name列中的单词模型而不是我做的 说明或ProductType列。

当然,如果这个词在所有3列中,那么我希望它的排名高于它在名称列中的排名。有没有什么方法可以让行排名更高,如果它只出现在Name / Description in Description / ProductType?

3 个答案:

答案 0 :(得分:10)

您可以执行以下查询。这里,WeightedRank是通过乘以各个匹配的等级来计算的。注意:不幸的是我没有安装Northwind,所以我无法测试它,所以看看它更像伪代码,让我知道它是否不起作用。

declare @searchTerm varchar(50) = 'model';

 SELECT 100 * coalesce(ct1.RANK, 0) +
        10 * coalesce(ct2.RANK, 0) +
        1 * coalesce(ct3.RANK, 0) as WeightedRank,
        *
   FROM dbo.Product
            LEFT JOIN
        CONTAINSTABLE(Product, Name, @searchTerm) ct1 ON ct.[Key] = Product.ProductID
            LEFT JOIN
        CONTAINSTABLE(Product, Description, @searchTerm) ct2 ON ct.[Key] = Product.ProductID
            LEFT JOIN
        CONTAINSTABLE(Product, ProductType, @searchTerm) ct3 ON ct.[Key] = Product.ProductID

答案 1 :(得分:5)

Listing 3-25. Sample Column Rank-Multiplier Search

Pro Full-Text Search in SQL Server 2008

SELECT *
FROM (
    SELECT Commentary_ID
        ,SUM([Rank]) AS Rank
    FROM (
        SELECT bc.Commentary_ID
            ,c.[RANK] * 10 AS [Rank]
        FROM FREETEXTTABLE(dbo.Contributor_Birth_Place, *, N'England') c
        INNER JOIN dbo.Contributor_Book cb ON c.[KEY] = cb.Contributor_ID
        INNER JOIN dbo.Book_Commentary bc ON cb.Book_ID = bc.Book_ID

        UNION ALL

        SELECT c.[KEY]
            ,c.[RANK] * 5
        FROM FREETEXTTABLE(dbo.Commentary, Commentary, N'England') c

        UNION ALL

        SELECT ac.[KEY]
            ,ac.[RANK]
        FROM FREETEXTTABLE(dbo.Commentary, Article_Content, N'England') ac
        ) s
    GROUP BY Commentary_ID
    ) s1
INNER JOIN dbo.Commentary c1 ON c1.Commentary_ID = s1.Commentary_ID
ORDER BY [Rank] DESC;

答案 2 :(得分:0)

类似于Henry的解决方案,但经过简化,测试并使用所提供问题的细节。

注意:我对联合和左联接样式都进行了性能测试,发现下面的数据集YMMV对下面的联合样式的逻辑读取要少得多。

 declare @searchTerm varchar(50) = 'model';
 declare @nameWeight int = 100;
 declare @descriptionWeight int = 10;
 declare @productTypeWeight int = 1;
 
 SELECT ranksGroupedByProductID.*, outerProduct.*
FROM   (SELECT [key],
               Sum([rank]) AS WeightedRank 
        FROM   (
                -- Each column that needs to be weighted separately 
                -- should be added here and unioned with the other queries
                SELECT [key],
                       [rank] * @nameWeight as [rank]
                FROM   Containstable(dbo.Product, [Name], @searchTerm) 
                       
                UNION ALL
                
                SELECT [key],
                       [rank] * @descriptionWeight as [rank]
                FROM   Containstable(dbo.Product, [Description], @searchTerm) 
                       
                UNION ALL

                SELECT [key],
                       [rank] * @productTypeWeight as [rank]
                FROM   Containstable(dbo.Product, [ProductType], @searchTerm) 
                       
                ) innerSearch

       -- Grouping by key allows us to sum each ProductID's ranks for all the columns
        GROUP  BY [key]) ranksGroupedByProductID

        -- This join is just to get the full Product table columns 
        -- and is optional if you only need the ordered ProductIDs
       INNER JOIN dbo.Product outerProduct
               ON outerProduct.ProductID = ranksGroupedByProductID.[key]

ORDER  BY WeightedRank DESC;