7

目前我有一个表,我搜索 4 个字段,FirstName、LastName、MiddleName 和 AKA。我目前对行进行了CONTAINSTABLE搜索,并且可以正常工作。不太好,但它有效。现在我想让名字的权重更高,中间名的权重更低。

我找到了命令ISABOUT但如果我必须按单词而不是列来执行它似乎毫无价值(希望我理解错了)。如果它是逐字的,这不是一个选项,因为我不知道用户将输入多少字。

我在这里找到了讨论相同解决方案的线程,但是我无法使公认的解决方案起作用。也许我做错了什么,但无论如何我都无法让它工作,它的逻辑似乎真的……很奇怪。必须有一个更简单的方法。

4

5 回答 5

8

操纵排名的关键是使用联合。对于每一列,您使用单独的选择语句。在该语句中,添加一个标识符,该标识符显示每行是从哪一列中提取的。将结果插入到表变量中,然后您可以通过对标识符进行排序或将排名乘以基于标识符的某个值来操纵排名。

关键是给出修改排名的表象,而不是实际改变sql server的排名。

使用表变量的示例:

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

对于表 People with Columns 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。

于 2008-11-26T21:15:30.837 回答
3

排名在索引中是无用的,您不能合并它们并期望结果意味着任何东西。每个指标的排名数字是苹果/橙/葡萄/西瓜/对的比较,没有相对意义WRT其他指标的内容。

当然,您可以尝试在索引之间链接/权重/顺序排名,以尝试捏造有意义的结果,但最终结果仍然是胡言乱语,但可能仍然足够好,可以根据您的具体情况提供可行的解决方案。

在我看来,最好的解决方案是将您打算可搜索的所有数据放在单个 FTS 索引/列中,并使用该列排名来对您的输出进行排序。即使您必须复制字段内容来完成结果。

于 2008-11-30T05:32:36.793 回答
2

就在几周前,我正在解决非常相似的问题,并且解决方案非常简单(尽管丑陋且占用空间)。FirstName + FirstName + LastName + MiddleName按此顺序创建包含 的组合值的另一列。Duplicate FirstName 列不是拼写错误,它是一种在搜索过程中强制 FT 将 FirstName 中的值权重更高的技巧。

于 2010-11-08T14:59:29.697 回答
1

这种方式怎么样:

    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记录生成一个记录,其中名字或中间名(或两者)在搜索词上匹配,并按与名字的所有匹配项排序(按降序排列),然后是与中间名的所有匹配项(再次按降序排列)

于 2014-06-05T08:45:43.213 回答
0

我假设返回的数据已连接到您的架构中的其他表?我会根据从关联数据到全文索引的列开发自己的 RANK。这也保证了 RANK 值的准确度。

于 2008-12-04T09:52:09.093 回答