合并 SQL 服务器中的记录

Merge records in SQL SERVER

我需要规范化 table 包含的数据。 这是一个包含一些行的示例 table:

Id LastName FirsName 地址 Email 电话 Mobile Age
1 罗西·马里奥 Via Milano NULL 123456 NULL 41
2 罗西马里奥 NULL rm@test.it 123456 NULL NULL
3 罗西·马里奥 Via Milano NULL NULL 254521 NULL

我想合并记录中的值,以便拥有一个包含所有值的唯一记录。 像这样:

Id LastName FirsName 地址 Email 电话 Mobile Age
1 罗西·马里奥 Via Milano rm@test.it 123456 254521 41

我尝试使用 MERGE 语句,但我认为这不是正确的解决方案。

感谢任何帮助。

我认为这可能对您有所帮助:-

UPDATE TAB_NAME
SET ID = MIN(ID), LastName = MAX(LastName), FirsName = MAX(FirsName)
    Address = MAX(Address), Email = MAX(Email), Tel = MAX(Tel), 
    Mobile = MAX(Mobile), Age = MAX(Age)
WHERE COND.;

如果您考虑将 FirstNameLastName 作为关键标识符,那么您可以这样写:

SELECT MIN(Id),     
       T1.LastName ,
       T1.FirsName,       
        SUBSTRING ((SELECT DISTINCT  CASE WHEN T2.Address IS NULL
        THEN '' ELSE ','+ T2.Address END  
        FROM @Test T2 
        WHERE T1.LastName = T2.LastName AND T1.FirsName = T2.FirsName
        FOR XML PATH('')),2,8000) AS [Address],
        SUBSTRING ((SELECT DISTINCT  CASE WHEN T3.Email  IS NULL 
        THEN '' ELSE ','+ T3.Email END
        FROM @Test T3 
        WHERE T1.LastName = T3.LastName AND T1.FirsName = T3.FirsName
    FOR XML PATH('')),2,8000)AS Email
FROM @Test T1
GROUP BY T1.LastName ,T1.FirsName

您正在查看两步操作。将合并的数据插入新的 table 然后删除原始 table 或使用合并的数据更新一行并删除所有额外的行。乍一看,前一种方法似乎最简单。

insert into NewTable( ID, LastName, FirstName, Address, Email, ...
    select  Min( ID ), LastName, FirstName, Min( Address ), Min( Email ), ...
from   OldTable
group by LastName, FirstName;

drop   OldTable;

exec sp_rename 'NewTable', 'OldTable'; -- Optional

但您可能没有删除和重命名 table 的权限。另外,您必须确保复制任何触发器、索引、约束等。

后一种方法在 DML 方面有点棘手,但更安全。

with
New as(
    select  Min( ID ) MinID, LastName, FirstName,
            Min( Address ) MinAddr, Min( Email ) MinEmail, 
            Min( Tel ) MinTel, Min( Mobile ) MinMobil, Min( Age ) MinAge
    from    OldTable
    group by LastName, FirstName
)
update  Old
    set Old.Address = New.MinAddr,
        Old.Email   = New.MinEmail,
        Old.Tel     = New.MinTel,
        Old.Mobile  = New.MinMobil,
        Old.Age     = New.MinAge
from    OldTable    Old
join    New
    on  New.MinID = Old.ID;

select * from OldTable;

with
MinIDs as(
    select  Min( ID ) MinID, LastName, FirstName
    from    OldTable
    group by LastName, FirstName
)
delete from Old
from    OldTable Old
join    MinIDs    MI
    on  MI.MinID < Old.ID;

如果您对非关键字段使用 MinMax 真的没有关系。这是后一种方法的Fiddle