当前位置: 首页 > 面试题库 >

SQL模糊联接-MSSQL

万楷
2023-03-14
问题内容

我有两组数据。现有客户和潜在客户。

我的主要目标是弄清楚是否有任何潜在客户已经是现有客户。但是,跨数据集的客户命名约定不一致。

现有客户

Customer /  ID
Ed's Barbershop /   1002
GroceryTown /   1003
Candy Place /   1004
Handy Man / 1005

潜在客户

Customer
Eds Barbershop
Grocery Town
Candy Place
Handee Man
Beauty Salon
The Apple Farm
Igloo Ice Cream
Ride-a-Long Bikes

我想写一些如下所示的选择语句来达到我的目标:

SELECT a.Customer, b.ID
FROM PotentialCustomers a LEFT JOIN
     ExistingCustomers B
     ON a.Customer = b.Customer

结果如下所示:

Customer /  ID
Eds Barbershop  / 1002
Grocery Town    / 1003
Candy Place / 1004
Handee Man  / 1005
Beauty Salon /  NULL
The Apple Farm /    NULL
Igloo Ice Cream / NULL
Ride-a-Long Bikes / NULL

我对Levenshtein距离和Double Metaphone的概念含糊其词,但我不确定如何在此处应用它。

理想情况下,我希望SELECT语句的JOIN部分读取类似以下内容:LEFT JOIN ExistingCustomers as B WHERE a.Customer LIKE b.Customer但我知道语法不正确。

任何建议都欢迎。谢谢!


问题答案:

这是使用Levenshtein Distance可以完成的方法:

创建此函数:(首先执行此操作)

CREATE FUNCTION ufn_levenshtein(@s1 nvarchar(3999), @s2 nvarchar(3999))
RETURNS int
AS
BEGIN
 DECLARE @s1_len int, @s2_len int
 DECLARE @i int, @j int, @s1_char nchar, @c int, @c_temp int
 DECLARE @cv0 varbinary(8000), @cv1 varbinary(8000)

 SELECT
  @s1_len = LEN(@s1),
  @s2_len = LEN(@s2),
  @cv1 = 0x0000,
  @j = 1, @i = 1, @c = 0

 WHILE @j <= @s2_len
  SELECT @cv1 = @cv1 + CAST(@j AS binary(2)), @j = @j + 1

 WHILE @i <= @s1_len
 BEGIN
  SELECT
   @s1_char = SUBSTRING(@s1, @i, 1),
   @c = @i,
   @cv0 = CAST(@i AS binary(2)),
   @j = 1

  WHILE @j <= @s2_len
  BEGIN
   SET @c = @c + 1
   SET @c_temp = CAST(SUBSTRING(@cv1, @j+@j-1, 2) AS int) +
    CASE WHEN @s1_char = SUBSTRING(@s2, @j, 1) THEN 0 ELSE 1 END
   IF @c > @c_temp SET @c = @c_temp
   SET @c_temp = CAST(SUBSTRING(@cv1, @j+@j+1, 2) AS int)+1
   IF @c > @c_temp SET @c = @c_temp
   SELECT @cv0 = @cv0 + CAST(@c AS binary(2)), @j = @j + 1
 END

 SELECT @cv1 = @cv0, @i = @i + 1
 END

 RETURN @c
END

(功能由Joseph Gama开发)

然后只需使用此查询即可获取匹配项

SELECT A.Customer,
       b.ID,
       b.Customer
FROM #POTENTIALCUSTOMERS a
     LEFT JOIN #ExistingCustomers b ON dbo.ufn_levenshtein(REPLACE(A.Customer, ' ', ''), REPLACE(B.Customer, ' ', '')) < 5;

创建该函数后,请完成脚本:

IF OBJECT_ID('tempdb..#ExistingCustomers') IS NOT NULL
    DROP TABLE #ExistingCustomers;

CREATE TABLE #ExistingCustomers
(Customer VARCHAR(255),
 ID       INT
);

INSERT INTO #ExistingCustomers
VALUES
('Ed''s Barbershop',
 1002
);

INSERT INTO #ExistingCustomers
VALUES
('GroceryTown',
 1003
);

INSERT INTO #ExistingCustomers
VALUES
('Candy Place',
 1004
);

INSERT INTO #ExistingCustomers
VALUES
('Handy Man',
 1005
);

IF OBJECT_ID('tempdb..#POTENTIALCUSTOMERS') IS NOT NULL
    DROP TABLE #POTENTIALCUSTOMERS;

CREATE TABLE #POTENTIALCUSTOMERS(Customer VARCHAR(255));

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Eds Barbershop');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Grocery Town');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Candy Place');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Handee Man');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Beauty Salon');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('The Apple Farm');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Igloo Ice Cream');

INSERT INTO #POTENTIALCUSTOMERS
VALUES('Ride-a-Long Bikes');

SELECT A.Customer,
       b.ID,
       b.Customer
FROM #POTENTIALCUSTOMERS a
     LEFT JOIN #ExistingCustomers b ON dbo.ufn_levenshtein(REPLACE(A.Customer, ' ', ''), REPLACE(B.Customer, ' ', '')) < 5;

在这里,您可以在以下网址找到T-
SQL示例:http://www.kodyaz.com/articles/fuzzy-string-matching-using-levenshtein-
distance-sql-server.aspx



 类似资料:
  • 问题内容: 我需要修改一个SQL表以将名称稍有不匹配的分组,并为该分组中的所有元素分配一个标准化名称。 例如,如果初始表如下所示: 我想创建一个新表或向现有表中添加一个字段,如下所示: 在这种情况下,我选择了要分配的第一个名称作为“标准名称”,但是我实际上并不在乎选择哪个名称- 最终,最终的“标准名称”将被散列为唯一的人员ID。(我也欢迎直接使用数字ID的替代解决方案。)我也要匹配出生日期,因此实

  • 由于我的域类中存在不明确的关联,新添加的正在引发。 链接数组如下所示:

  • 问题内容: 我有三个表:R,S和P。 表R通过外键与S连接;有 应该 是S中至少一个的记录,所以我可以加入: 如果S中没有记录,那么我没有行,那很好。 然后表S与P联接,其中记录为P可能存在,也可能不存在,并与S联接。 所以我做 如果我想将第二个JOIN绑定到S而不是R,例如我可以使用括号,该怎么办: 还是这已经是R,S和P之间笛卡尔积的自然行为? 问题答案: 各种外部联接和普通联接都在相同的优先

  • 注意: Internet Explorer和Safari不支持SVG滤镜! <defs> 和 <filter> 所有互联网的SVG滤镜定义在<defs>元素中。<defs>元素定义短并含有特殊元素(如滤镜)定义。 <filter>标签用来定义SVG滤镜。<filter>标签使用必需的id属性来定义向图形应用哪个滤镜? SVG <feGaussianBlur> 实例 1 <feGaussianBlu

  • 什么是SQL和什么是不同的类型?

  • 问题内容: 我们正在开发ETL作业,并且我们的顾问在连接表时一直使用“旧式” SQL 而不是使用内部连接子句 我的问题是,从长远来看,使用旧的“ where join”是否存在风险?这种联接被支持并保持为ANSI标准的时间有多长?我们的平台是SQL Server,我的主要原因是将来不再支持这些“ where joins”。发生这种情况时,我们必须使用“内部联接”样式的联接来修改所有ETL作业。 问