我目前正在开展一个项目,我想通过一个输入搜索词来搜索员工。为此我使用的是SQL FTS。
表架构看起来像这样
员工表
EmployeeId,名字,姓氏
示例数据
1,John,Miller
2,查克,诺里斯
地址表
AddressId,EmployeeId,CityId,Street,StreetNumber
示例数据
1,1,1,Avenue,12
2,2,2,Wimbledon Rd,12
城市表
CityId,Name,ZipCode
示例数据
1,汉堡,22335
2,伦敦,12345
所以现在我得到了以下搜索词:
现在问题在于,使用CONTAINSTABLE只允许一次搜索一个表。因此,在“雇员全文”目录上应用“John AND Hamburg”会返回0条记录,因为“Hamburg”位于地址表中。
所以目前我只能使用“OR”代替“AND”,例如:
SELECT
(keyTblSp.RANK * 3) AS [Rank],
sp.*
FROM Employee sp
INNER JOIN
CONTAINSTABLE(Employee, *, 'John OR Hamburg', 1000) AS keyTblSp
ON sp.EmployeeId = keyTblSp.[KEY]
UNION ALL
SELECT
(keyTbl.RANK * 2) AS [Rank],
sp.*
FROM Employee sp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId
INNER JOIN
CONTAINSTABLE([Address], *, 'John OR Hamburg', 1000) AS keyTbl
ON addr.AddressId = keyTbl.[KEY]
UNION ALL
SELECT
(keyTbl.RANK * 2) AS [Rank],
sp.*
FROM Employee sp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId
LEFT OUTER JOIN [City] cty ON cty.CityId = addr.CityId
INNER JOIN
CONTAINSTABLE([City], *, 'John OR Hamburg', 1000) AS keyTbl
ON cty.CityId = keyTbl.[KEY]
这导致不仅生活在汉堡的约翰被归还,而且每个人都叫约翰和每个住在汉堡的人。 我能想到的一个解决方案是以某种方式计算Employee Table中的一列,该列包含全文搜索的所有必要值,如。
员工表
EmployeeId,名字,姓氏, FulltextColumn
示例数据
1 |约翰|米勒| John Miller Avenue 12 Hamburg 22335
那么我就可以做到
SELECT
(keyTbl.RANK) AS [Rank],
sp.*
FROM Employee sp
INNER JOIN
CONTAINSTABLE([Employee], FulltextColumn, 'John AND Hamburg', 1000) AS keyTbl
ON sp.EmployeeId = keyTbl.[KEY]
这可能吗?还有其他想法吗?
答案 0 :(得分:1)
您可以使用联接来要求地址和人名匹配。
SELECT
(keyTblSp.RANK * 3) AS [Rank],
sp.*
FROM Employee sp
INNER JOIN
CONTAINSTABLE(Employee, *, 'John OR Hamburg', 1000) AS keyTblSp
ON sp.EmployeeId = keyTblSp.[KEY]
join
(
SELECT
(keyTbl.RANK * 2) AS [Rank],
sp.*
FROM Employee sp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId
INNER JOIN
CONTAINSTABLE([Address], *, 'John OR Hamburg', 1000) AS keyTbl
ON addr.AddressId = keyTbl.[KEY]
UNION ALL
SELECT
(keyTbl.RANK * 2) AS [Rank],
sp.*
FROM Employee sp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId
LEFT OUTER JOIN [City] cty ON cty.CityId = addr.CityId
INNER JOIN
CONTAINSTABLE([City], *, 'John OR Hamburg', 1000) AS keyTbl
ON cty.CityId = keyTbl.[KEY]
) addr_matches
on addr_matches.EmployeeId = sp.EmployeeId
我认为这会给你指定的结果,显然,这需要一个名称和一个地址搜索术语来搜索返回任何结果。你没有说明如果有人只是搜索“John”会发生什么,如果你总是得到一个名字和地址,我认为上面的工作会很好。
答案 1 :(得分:0)
我认为计算列是您的最佳选择。它将是最灵活的,因为你不知道搜索查询中会有哪些令牌,它会表现得更好,而你的存储过程会更小。
为了根据另一个表中的数据创建计算列,您必须使用这样的UDF(用户定义函数)创建它:
CREATE FUNCTION dbo.udf_ComputedColumnFunction (
@EmployeeId INT
)
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE @RET VARCHAR(1000)
SELECT
@RET = e.FirstName + ' ' + e.LastName + ' ' + a.Street + ' ' + a.StreetNumber + ' ' + c.Name + ' ' + c.ZipCode
FROM Employee e
INNER JOIN Address a ON a.EmployeeId = e.EmployeeId
INNER JOIN City c ON c.CityId = a.CityId
RETURN @RET
END
GO
ALTER TABLE Employee
ADD SearchColumn AS dbo.udf_ComputedColumnFunction(EmployeeId)
如果你不想这样做,你可以:
答案 2 :(得分:0)
我认为您应该创建并索引视图,并且应该将可以在FullText中使用的所有列连接在一个列中,方法是用空格或短划线将它们分开,因为两者都是sql server 2005的干扰词。然后在索引视图创建全文索引。
包含表格默认情况下不适用FormsOf Inflectional或Thesaurus表格。这两个是配置和使用的好选择。
如果你只想去“OR”,那就使用FreeTextTable,好像默认情况下同时应用同义词库和FormsOf屈折形式。