检查表2的其他列中表1的列的所有单词的存在

时间:2013-08-22 08:49:38

标签: sql sql-server sql-server-2008

我有一个包含product_name字段的表。然后是另一张带模型的表。

===products
product_id, product_name

===models
model_id, model_name

我正在寻找以下方法。

  1. 型号名称可以用连字符分隔,即JVC-600-BLACK
  2. 对于每个模型,我需要检查产品名称中模型的每个单词是否存在。
  3. 我需要在下面的某些地方找到结果。

    == results
    model_id, product_id
    

    如果有人能指出我正确的方向,那将是一个很大的帮助。

    备注

    1. 这些是巨大的表,有大约数百万条记录和数量 model_name中的单词不固定。
    2. 模型中的单词可以以任何顺序存在,也可以存在于产品名称之间或其他单词中

3 个答案:

答案 0 :(得分:1)

这是一个函数,它使用-作为分隔符将第一个字符串拆分为多个部分,并查找第二个字符串中的每个部分,如果找到所有部分,则返回1,否则返回0

CREATE FUNCTION dbo.func(@str1 varchar(max), @str2 varchar(max))
RETURNS BIT
AS
BEGIN
  DECLARE @pos INT, @newPos INT,
          @delimiter NCHAR(1)
  SET @delimiter = '-'
  SET @pos = 1
  SET @newPos = 0

  WHILE (@newPos < LEN(@str1))
  BEGIN
    SET @newPos = CHARINDEX(@delimiter, @str1, @pos)
    IF @newPos = 0
      SET @newPos = LEN(@str1)+1
    DECLARE @data2 NVARCHAR(MAX)
    SET @data2 = SUBSTRING(@str1, @pos, @newPos-@pos)

    IF CHARINDEX(@data2, @str2) = 0
      RETURN 0

    SET @pos = @newPos + 1
    IF @newPos = 0
      BREAK
  END
  RETURN 1
END

您可以按照以下方式使用上述功能:

SELECT model_id, product_id
FROM models
JOIN products 
  ON dbo.func(models.model_name, products.product_name) = 1

它不会很快,但我不认为存在快速解决方案,因为您的问题不允许索引。有可能更改数据库结构以实现此目的,但是如何完成此操作在很大程度上取决于您的数据是什么样的。

答案 1 :(得分:1)

我不知道这个解决方案是否更快,你可以检查一下你是否在乎:

--=======================
-- sample data
-- ======================
declare @Products table
(
    product_id int,
    product_name nvarchar(max)
)

insert into @Products select 1, 'sdfsd def1 abc1klm1 sdljkfd'
insert into @Products select 2, 'sdfsd def2 abc2klm2 sdljkfd'
insert into @Products select 3, 'sdfsd def3 abc3klm3 sdljkfd'


declare @Models table
(
    model_id int,
    model_name nvarchar(max)
)

insert into @Models select 1, 'abc1-def1-klm1'
insert into @Models select 2, 'abc2-def2-klm2'
insert into @Models select 3, 'abc3-def3-klm3'


--=======================
-- solution
-- ======================
select t1.product_id, t2.model_id from @Products t1
cross join (
select 
    t1.model_id, Word = t2.r.value('.', 'nvarchar(max)') 
from (select model_id, x = cast('<e>' + replace(model_name, '-', '</e><e>') + '</e>' as xml) from @Models ) t1
cross apply x.nodes('e') as t2 (r)
) t2
group by product_id, model_id
having min(charindex(word, product_name)) != 0

答案 2 :(得分:0)

您可能需要考虑使用SQL Server的Full Text Search功能。简而言之,它会在设置时指定的表和列中对所有单词进行编目(忽略“和”,“或”,“a”和“默认值”等噪声词,但这个噪声世界列表是可配置的)完整文本目录并提供一些功能,允许您利用该目录快速查找行。