2015-02-05 3 views
1

Мне нужно нормализовать таблицу, содержащую абзацные данные. Вот пример таблицы с некоторыми строками:Объединить записи в SQL SERVER

 
Id LastName FirsName Address Email  Tel  Mobile Age 
1 Rossi Mario Via Milano NULL  123456 NULL 41 
2 Rossi Mario NULL  [email protected] 123456 NULL NULL 
3 Rossi Mario Via Milano NULL  NULL 254521 NULL 

Я хочу, чтобы объединить значения в записях, чтобы иметь одну уникальную запись со всеми значениями. Как это:

 
Id LastName FirsName Address Email  Tel  Mobile Age 
1 Rossi Mario Via Milano [email protected] 123456 254521 41 

Я пытался использовать оператор MERGE, но я не думаю, что это правильное решение.

Любая помощь приветствуется.

+2

Как вы решаете, какие записи должны быть объединены? –

+0

вы должны прояснить все разные сценарии. Как и если есть два адреса для одного и того же человека или двух мобильных и т. Д. BTW Deepshikha запрос хорош. – KumarHarsh

+0

Привет. Спасибо за ваш ответ. Если две записи имеют два разных адреса, я не хочу объединять эту запись. – skysurfer

ответ

1

Если вы рассматриваете FirstName и LastName в качестве ключевых идентификаторов, то вы можете написать как:

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 
+0

Отлично! Я не знал FOR XML PATH. Большое спасибо! – skysurfer

0

Я думаю, что это может поможет вам: -

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.; 
0

Вы смотрите на два шага операция. Либо вставьте объединенные данные в новую таблицу, затем отбросьте исходную таблицу или обновите одну строку с объединенными данными и удалите все лишние строки. На первый взгляд, первый метод кажется самым легким на сегодняшний день.

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 

Но у вас могут не быть привилегии перебрасывать и переименовывать таблицы. Кроме того, вы должны убедиться, что вы дублируете любые триггеры, индексы, ограничения и т. Д.

Последний метод немного сложнее, чем 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; 

И это на самом деле не имеет значения, если вы используете Min или Max с неключевых полей. Вот Fiddle для последнего метода.

Смежные вопросы