sql - Find Last Record in Chain - 一个客户合并过程

标签 sql tsql sql-server-2016

我正在从另一个供应商的系统导入客户数据,我们有合并流程,我们使用这些流程来识别潜在的重复客户帐户,如果他们满足特定条件(例如相同的名字、姓氏、SSN 和 DOB),它们就会合并它们。在此过程中,我看到我们正在创建链的位置 - 例如,客户 A 被合并到客户 B,然后客户 B 又被合并到客户 C。

我希望用它来识别这些链并更新客户记录以指向链中的最后一条记录。因此,在我上面的示例中,客户 A 和客户 B 的合并收件人字段中都会包含客户 C 的 ID。

CustID FName   LName     CustStatusType  isMerged  MergedTo
1      Kevin   Smith     M               1         2 
2      Kevin   Smith     M               1         3
3      Kevin   Smith     M               1         4
4      Kevin   Smith     O               0         NULL
5      Mary    Jones     O               0         NULL
6      Wyatt   Earp      M               1         7
7      Wyatt   Earp      O               1         NULL
8      Bruce   Wayn      M               1         10
9      Brice   Wayne     M               1         10
10     Bruce   Wane      M               1         11
11     Bruce   Wayne     O               1         NULL

CustStatusType 指示客户帐户是打开的 (“O”) 还是合并的 (“M”)。然后我们有一个 isMerged 字段作为 BIT 字段,指示帐户是否已合并,最后是 MergedTo 字段,指示记录被合并到哪个客户帐户。

通过提供的示例,我想要实现的是将 1 和 2 的 CustID 记录的 MergedTo 记录设置为 3 - 而 CustID 3 可以更新或保留原样。对于客户 ID 4、5 和 6 - 这些记录已找到并且不需要更新。但是在客户 ID 8 - 10 上,我希望将这些记录设置为 11 - 如下表所示。

CustID FName   LName     CustStatusType  isMerged  MergedTo
1      Kevin   Smith     M               1         4 
2      Kevin   Smith     M               1         4
3      Kevin   Smith     M               1         4
4      Kevin   Smith     O               0         NULL
5      Mary    Jones     O               0         NULL
6      Wyatt   Earp      M               1         7
7      Wyatt   Earp      O               1         NULL
8      Bruce   Wayn      M               1         11
9      Brice   Wayne     M               1         11
10     Bruce   Wane      M               1         11
11     Bruce   Wayne     O               1         NULL

我一直无法弄清楚如何使用 TSQL 实现此目的 - 建议?

测试数据:

DROP TABLE IF EXISTS #Customers;

CREATE TABLE #Customers
    (
        CustomerID INT ,
        FirstName VARCHAR (25) ,
        LastName VARCHAR (25) ,
        CustomerStatusTypeID VARCHAR (1) ,
        isMerged BIT ,
        MergedTo INT
    );
INSERT INTO #Customers
VALUES ( 1, 'Kevin', 'Smith', 'M', 1, 2 ) ,
       ( 2, 'Kevin', 'Smith', 'M', 1, 3 ) ,
       ( 3, 'Kevin', 'Smith', 'M', 1, 4 ) ,
       ( 4, 'Kevin', 'Smith', 'O', 0, NULL ) ,
       ( 5, 'Mary', 'Jones', 'O', 0, NULL ) ,
       ( 6, 'Wyatt', 'Earp', 'M', 1, 7 ) ,
       ( 7, 'Wyatt', 'Earp', 'O', 1, NULL ) ,
       ( 8, 'Bruce', 'Wayn', 'M', 1, 10 ) ,
       ( 9, 'Brice', 'Wayne', 'M', 1, 10 ) ,
       ( 10, 'Bruce', 'Wane', 'M', 1, 11 ) ,
       ( 11, 'Bruce', 'Wayne', 'O', 1, NULL );

SELECT *
FROM   #Customers;

DROP TABLE #Customers;

最佳答案

例如soundex()似乎足够好了。它返回一个代码,该代码基于单词的英语发音。在名字和姓氏上使用它来连接客户表和查询客户表的子查询,添加 row_number() 按名称的 Soundex 分区并按 ID 降序排列 -- 到数字带 1 的“最新”记录。对于连接条件,使用名称的 Soundex、行号 1,当然还有 ID 的不等式。

UPDATE c1
       SET c1.mergedto = x.customerid
       FROM #customers c1
            LEFT JOIN (SELECT c2.customerid,
                              soundex(c2.firstname) sefn,
                              soundex(c2.lastname) seln,
                              row_number() OVER (PARTITION BY soundex(c2.firstname),
                                                              soundex(c2.lastname)
                                                 ORDER BY c2.customerid DESC) rn
                              FROM #customers c2) x
                      ON x.sefn = soundex(c1.firstname)
                         AND x.seln = soundex(c1.lastname)
                         AND x.rn = 1
                         AND x.customerid <> c1.customerid;

db<>fiddle

我真的不明白 customerstatustypeidismerged 列背后的概念。据我了解,它们都是从 mergedto 是否为 null 派生出来的。但是样本数据既不是预期结果也不支持这一点。但是由于这些列显然不会在您的样本输入和输出之间发生变化,我想没关系,我只是让它们单独存在。

如果证明 Soundex 不足以满足您的需求,您可能需要寻找其他字符串距离指标,例如 Levenshtein distance .据我所知,SQL Server 中没有包含它的实现,但搜索引擎可能会吐出第三方的实现,或者可能有一些可以通过 CLR 使用的东西。当然,您也可以自己动手。

关于sql - Find Last Record in Chain - 一个客户合并过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54000259/

相关文章:

sql-server - 为什么我需要两个 SQL Server Service Broker 队列来完成一个简单的任务?

sql-server - 如何分离变量和值,然后插入表中?

sql - 生成范围之间的数字

mysql - 迭代两列并比较它们

PHP-laravel : How to handle time overlapping in database?

sql-server-2008 - 用于标签的 GUID 与身份

sql - 在SQL中使用格式将数字转换为varchar

sql-server - Visual Studio 2015 Update 2 和 Sql Server 2016 架构比较

MySQL:如何在所有表中级联列类型设置?

mysql - 在插入查询中使用集合