Sql server 2005 SQL Server全文搜索-创建一个计算列

Sql server 2005 SQL Server全文搜索-创建一个计算列,sql-server-2005,tsql,full-text-search,Sql Server 2005,Tsql,Full Text Search,我目前正在从事一个项目,我想通过一个输入搜索词搜索员工。为此,我使用了SQLFTS 表架构如下所示 员工表 EmployeeId,名字,姓氏 样本数据 约翰,米勒 2,查克,诺里斯 地址表 地址ID、雇员ID、城市ID、街道、街道号 样本数据 12号大街1号,1号,1号 温布尔登路2号,2号,2号,12号 城市表 城市ID、名称、ZipCode 样本数据 汉堡,22335 伦敦,12345 现在我得到了以下搜索词: 约翰·汉堡:指约翰和汉堡,应返回1张唱片 John London:表示J

我目前正在从事一个项目,我想通过一个输入搜索词搜索员工。为此,我使用了SQLFTS

表架构如下所示

员工表

EmployeeId,名字,姓氏

样本数据

约翰,米勒

2,查克,诺里斯


地址表

地址ID、雇员ID、城市ID、街道、街道号

样本数据

12号大街1号,1号,1号

温布尔登路2号,2号,2号,12号


城市表

城市ID、名称、ZipCode

样本数据

汉堡,22335

伦敦,12345


现在我得到了以下搜索词:

  • 约翰·汉堡:指约翰和汉堡,应返回1张唱片
  • John London:表示John和London,由于伦敦没有John,因此应返回0条记录
  • 诺里斯温布尔登:指诺里斯和温布尔登,应返回1条记录
现在的问题是使用CONTAINSTABLE一次只允许搜索一个表。因此,对员工全文目录应用“John AND Hamburg”将返回0条记录,因为“Hamburg”位于地址表中

所以目前我只能用“或”代替“和”,比如:

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表中的一列,该列包含全文搜索所需的所有值,如

员工表

EmployeeId、Firstname、Lastname、FulltextColumn

样本数据

1 |约翰|米勒|约翰·米勒大道12号汉堡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] 

这可能吗?还有其他想法吗?

您可以使用连接要求地址和人名都匹配

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”会发生什么,如果你总是能同时得到姓名和地址,我想上面的方法会很好

您可以使用连接来要求地址和人名都匹配

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”会发生什么,如果你总是能同时得到姓名和地址,我想上面的方法会很好

我认为计算列是您最好的选择。它将是最灵活的,因为您不知道搜索查询中将包含哪些令牌,它将执行得更好,并且您的存储过程将更小

为了基于另一个表中的数据创建计算列,必须使用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)
如果您不想这样做,您可以:

  • 创建并添加全文索引
  • 创建由触发器或定期运行存储过程填充的查找表

我认为计算列是您最好的选择。它将是最灵活的,因为您不知道搜索查询中将包含哪些令牌,它将执行得更好,并且您的存储过程将更小

为了基于另一个表中的数据创建计算列,必须使用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)
如果您不想这样做,您可以:

  • 创建并添加全文索引
  • 创建由触发器或定期运行存储过程填充的查找表

我认为您应该创建和索引视图,并且应该通过使用空格或破折号将可用于全文的所有列合并到一个列中,因为它们都是sql server 2005的干扰词。然后在该索引视图上创建全文索引

Contains表默认情况下不应用词形变化或同义词表的形式。这两个是很好的配置和使用选项


如果您只想选择“或”,那么使用FreeTextTable,就好像默认情况下同时应用同义词库和屈折形式一样。

我认为您应该创建和索引视图,并且应该通过用空格或破折号分隔,将可用于全文的所有列合并到一个列中,因为它们都是sql server 2005的噪音词。然后在该索引视图上创建全文索引

Contains表默认情况下不应用词形变化或同义词表的形式。这两个是很好的配置和使用选项


如果您只想选择“或”,请使用FreeTextTable,就像默认情况下同时应用同义词库和词形变化表一样。

您好,谢谢您的建议。我知道有一个特殊的表格,在一列中包含所有必需的信息。存储过程用于通过使用每个参与表的触发器来更新索引。全文目录用于新表以执行快速搜索。您好,谢谢您的建议。我知道有一个特殊的表格,在一列中包含所有必需的信息。存储过程用于通过使用每个参与表的触发器来更新索引。全文目录用于新表以执行快速搜索。