【问题标题】:Get matching string with the percentage获取与百分比匹配的字符串
【发布时间】:2019-07-11 14:34:16
【问题描述】:

我有以下详细数据:

表 1:Table1 的大小在 few records 左右。

表 2:Table2 的行数为 50 millions

要求:我需要匹配从table1table2 的任意字符串列,例如name 列到name 并获取匹配百分比(注意列可以是任意,可能是地址或任何在单个单元格中有多个单词的字符串列)。

样本数据:

create table table1(id int, name varchar(100), address varchar(200));

insert into table1 values(1,'Mario Speedwagon','H No 10 High Street USA');
insert into table1 values(2,'Petey Cruiser Jack','#1 Church Street UK');
insert into table1 values(3,'Anna B Sthesia','#101 No 1 B Block UAE');    
insert into table1 values(4,'Paul A Molive','Main Road 12th Cross H No 2 USA');
insert into table1 values(5,'Bob Frapples','H No 20 High Street USA');    

create table table2(name varchar(100), address varchar(200), email varchar(100));

insert into table2 values('Speedwagon Mario ','USA, H No 10 High Street','mario@gmail.com');
insert into table2 values('Cruiser Petey Jack','UK #1 Church Street','jack@gmail.com');
insert into table2 values('Sthesia Anna','UAE #101 No 1 B Block','Aanna@gmail.com');    
insert into table2 values('Molive Paul','USA Main Road 12th Cross H No 2','APaul@gmail.com');
insert into table2 values('Frapples Bob ','USA H No 20 High Street','BobF@gmail.com');  

预期结果

    tbl1_Name               tbl2_Name           Percentage  
--------------------------------------------------------
Mario Speedwagon        Speedwagon Mario    100
Petey Cruiser Jack      Cruiser Petey Jack  100
Anna B Sthesia          Sthesia Anna        around 80+
Paul A Molive           Molive Paul         around 80+
Bob Frapples            Frapples Bob        100

注意:上面给出的只是要理解的示例数据,我在table1中有few records,在table2中有50 millions在实际的情景中。

我的尝试

第 1 步:按照Shnugo 的建议,将数据标准化并存储在同一个表中。

对于表 1:

ALTER TABLE table1 ADD Name_Normal VARCHAR(1000);
GO

--00:00:00 (5 row(s) affected)
UPDATE table1 
SET Name_Normal=CAST('<x>' + REPLACE((SELECT LOWER(name) AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)
                .query(N'
                        for $fragment in distinct-values(/x/text())
                        order by $fragment
                        return $fragment
                        ').value('.','nvarchar(1000)');           
GO

对于表 2:

ALTER TABLE table2 ADD Name_Normal VARCHAR(1000);
GO

--01:59:03 (50000000 row(s) affected)
UPDATE table2 
SET Name_Normal=CAST('<x>' + REPLACE((SELECT LOWER(name) AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)
                .query(N'
                        for $fragment in distinct-values(/x/text())
                        order by $fragment
                        return $fragment
                        ').value('.','nvarchar(1000)');           
GO  

第二步:使用Levenshtein distance in Microsoft Sql Server创建百分比计算函数

第 3 步:查询以获取匹配百分比。

--00:00:33 (23456 row(s) affected)
SELECT t.name AS [tbl1_Name],t1.name AS [tbl2_Name],
       dbo.ufn_Levenshtein(t.Name_Normal,t1.Name_Normal) percentage 
       into #TempTable
FROM table2 t
INNER JOIN table1 t1 
ON CHARINDEX(SOUNDEX(t.Name_Normal),SOUNDEX(t1.Name_Normal))>0 

--00:00:00 (23456 row(s) affected)
SELECT * 
FROM #TempTable 
WHERE percentage >= 50
order by percentage desc;

结论:得到了预期的结果,但它需要 2 hours 来规范化 table2,如上述查询中的评论中所述。在step 1table2 提供更好的优化建议?

【问题讨论】:

  • 为什么规范化操作需要多长时间很重要?这应该是一次性操作...想象一下将 50mio 字符串小写的必要工作,将它们拆分为片段并按排序顺序重新连接...正如您在另一个问题:对于STRING_SPLIT(),迁移到 SQL-Server 2016 真的很有帮助。您可能会尝试将这项工作转移到 CLR 函数。具有基于XQuery 的规范化的 XML 拆分器一定很慢...

标签: sql-server tsql sql-server-2008-r2


【解决方案1】:

您是否尝试过研究 DQS(数据质量服务)? 取决于您的 SQL 版本,它带有安装文件。 https://docs.microsoft.com/en-us/sql/data-quality-services/data-matching?view=sql-server-2017

【讨论】:

    猜你喜欢
    • 2019-07-07
    • 2020-08-28
    • 2021-02-05
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    相关资源
    最近更新 更多