2015-11-23 2 views
3

У меня есть старый источник данных, который разделен запятыми и запятыми. Первая точка с запятой указывает фамилию, вторая обозначает первое и среднее имя (или инициалы), а последняя точка с запятой указывает тип индивидуума. Запятая указывает, что началось новое имя. Вот пример этих данных.Удаление данных с помощью нескольких разделителей?

+-------+---------------------------------------------------------------------------------------------------------------------+ 
| ID | SOURCE                            | 
+-------+---------------------------------------------------------------------------------------------------------------------+ 
| 62963 | RENZ;MICHAEL;DECEASED,WANDER;MARIA;MINOR,WANDER;HENRY RUDOLPH;MINOR,WANDER;ROSA;MINOR,WANDER;PAUL EMIL;MINOR  | 
| 62964 | HERNDON;A C;ESTATE,BERRING;A F;DECEASED,BEIRING;A F;DECEASED,BEIRING;ANDREAS FREDERICK;DECEASED      | 
| 62965 | ZINCH;;ESTATE,ZINTZ;;ESTATE,HAYNES;HENRY;DECEASED                 | 
| 62965 | ZINCH;;ESTATE,ZINTZ;;ESTATE,HAYNES;HENRY;DECEASED                 | 
| 62966 | KRAUS;JOSEPHINE;MINOR,KENNEDY;GEORGE;DECEASED                  | 
| 62967 | CAREY;JAMES;ESTATE,DE LA GARZA;REFUGIO;DECEASED                  | 
| 62968 | LEWIS;FLORENCE;ESTATE,LOCKWOOD;ALBERT A;DECEASED                 | 
| 62969 | GLAESER;EMMA;MINOR,GLAESER;HERMAN JR;MINOR,GLAESER;HERMAN;MINOR,RODRIGUEZ;HILARIO;DECEASED,RODRIGUEZ;MARIE;DECEASED | 
| 62970 | STORY;BETTIE;ESTATE,EIGENDORFF;FRANZ;DECEASED                  | 
| 62971 | HOWELL;MAMIE;MINOR,HOWELL;ETHEL;MINOR                    | 
+-------+---------------------------------------------------------------------------------------------------------------------+ 

Я пытаюсь вытащить данные таким образом, как это:

+-----------+------------+-------------+-------------------+----------+ 
|  ID | SEQUENCE | LAST  | FIRSTMIDDLE | TYPE | 
+-----------+------------+-------------+-------------------+----------+ 
|  62963 |   1 | RENZ  | MICHAEL   | DECEASED | 
|  62963 |   2 | WANDER  | MARIA    | MINOR | 
|  62963 |   3 | WANDER  | HENRY RUDOLPH  | MINOR | 
|  62963 |   4 | WANDER  | ROSA    | MINOR | 
|  62963 |   5 | WANDER  | PAUL EMIL   | MINOR | 
|  62964 |   1 | HERNDON  | A C    | ESTATE | 
|  62964 |   2 | BERRING  | A F    | DECEASED | 
|  62964 |   3 | BEIRING  | A F    | DECEASED | 
|  62964 |   4 | BEIRING  | ANDREAS FREDERICK | DECEASED | 
|  62965 |   1 | ZINCH  |     | ESTATE | 
|  62965 |   2 | ZINTZ  |     | ESTATE | 
|  62965 |   3 | HAYNES  | HENRY    | DECEASED | 
|  62966 |   1 | KRAUS  | JOSEPHINE   | MINOR | 
|  62966 |   2 | KENNEDY  | GEORGE   | DECEASED | 
|  62967 |   1 | CAREY  | JAMES    | ESTATE | 
|  62967 |   2 | DE LA GARZA | REFUGIO   | DECEASED | 
|  62968 |   1 | LEWIS  | FLORENCE   | ESTATE | 
|  62968 |   2 | LOCKWOOD | ALBERT A   | DECEASED | 
|  62969 |   1 | GLAESER  | EMMA    | MINOR | 
|  62969 |   2 | GLAESER  | HERMAN JR   | MINOR | 
|  62969 |   3 | GLAESER  | HERMAN   | MINOR | 
|  62969 |   4 | RODRIGUEZ | HILARIO   | DECEASED | 
|  62969 |   5 | RODRIGUEZ | MARIE    | DECEASED | 
|  62970 |   1 | STORY  | BETTIE   | ESTATE | 
|  62970 |   2 | EIGENDORFF | FRANZ    | DECEASED | 
|  62971 |   1 | HOWELL  | MAMIE    | MINOR | 
|  62971 |   2 | HOWELL  | ETHEL    | MINOR | 
+-----------+------------+-------------+-------------------+----------+ 

Этого типа извлечения данных является то, что я не слишком хорошо знаком с. Я думаю, что мне нужно использовать сложную комбинацию SUBSTRING и CHARINDEX, но учитывая, что количество записей, которые может содержать исходный столбец, зависит от меня, я не уверен, как лучше всего подойти к этому. Любые указания о том, где я должен начать, были бы невероятно полезными.

+0

Google "SQL Функция Split" есть буквально тысячи примеров. – RBarryYoung

+0

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

+0

Синтаксические строки не предназначены для SQL. На самом деле это худшая идея. Считаете ли вы [SQL CLR Functions] (https://msdn.microsoft.com/en-us/library/ms189876.aspx)? – thepirat000

ответ

3

использование разбить строку концепции и parsename сделать это

SELECT id, 
     Row_number() 
     OVER (
      partition BY id 
      ORDER BY (SELECT NULL))AS sequence, 
     Parsename(Replace(col3, ';', '.'), 3) as LAST, 
     Parsename(Replace(col3, ';', '.'), 2) as FIRSTMIDDLE, 
     Parsename(Replace(col3, ';', '.'), 1) as TYPE 
FROM (SELECT id, 
       Split.a.value('.', 'VARCHAR(100)') col3 
     FROM (SELECT id, 
         Cast ('<M>' + Replace(item_id, ',', '</M><M>') 
          + '</M>' AS XML) AS Data 
       FROM #yourtable) AS A 
       CROSS APPLY Data.nodes ('/M') AS Split(a))a 
+0

Просто FYI, используя 'PARSENAME', быстро и просто, но он будет разбит, если в исходных данных будет период ('. '). Вам, вероятно, необходимо сначала преобразовать их в неиспользуемый символ, а затем преобразовать их обратно в период после того, как функция PARSENAME вернет значение. –

1
create table #temp (id int, [source] nvarchar(4000)) 

insert #temp (id, [source]) 
     select 62963, 'RENZ;MICHAEL;DECEASED,WANDER;MARIA;MINOR,WANDER;HENRY RUDOLPH;MINOR,WANDER;ROSA;MINOR,WANDER;PAUL EMIL;MINOR' 
union select 62964, 'HERNDON;A C;ESTATE,BERRING;A F;DECEASED,BEIRING;A F;DECEASED,BEIRING;ANDREAS FREDERICK;DECEASED' 
union select 62965, 'ZINCH;;ESTATE,ZINTZ;;ESTATE,HAYNES;HENRY;DECEASED' 
union select 62965, 'ZINCH;;ESTATE,ZINTZ;;ESTATE,HAYNES;HENRY;DECEASED' 
union select 62966, 'KRAUS;JOSEPHINE;MINOR,KENNEDY;GEORGE;DECEASED' 
union select 62967, 'CAREY;JAMES;ESTATE,DE LA GARZA;REFUGIO;DECEASED' 
union select 62968, 'LEWIS;FLORENCE;ESTATE,LOCKWOOD;ALBERT A;DECEASED' 
union select 62969, 'GLAESER;EMMA;MINOR,GLAESER;HERMAN JR;MINOR,GLAESER;HERMAN;MINOR,RODRIGUEZ;HILARIO;DECEASED,RODRIGUEZ;MARIE;DECEASED' 
union select 62970, 'STORY;BETTIE;ESTATE,EIGENDORFF;FRANZ;DECEASED' 
union select 62971, 'HOWELL;MAMIE;MINOR,HOWELL;ETHEL;MINOR' 

select id, 
    row_number() over(partition by id order by id) as [sequence], 
    [1] as [last], 
    [2] as [firstmiddle], 
    [3] as [type] 
from (
    select id, attributeid, attribute, 
     row_number() over(partition by attributeid order by personid) x 
    from (
     select id, 
      personid, 
      row_number() over(partition by personid order by personid) attributeid, 
      attribute 
     from (
      select id, 
       personid, 
       attribute = y.i.value('(./text())[1]', 'nvarchar(4000)') 
      from 
      ( 
       select id, personid, x = convert(xml, '<i>' 
        + replace(person, ';', '</i><i>') 
        + '</i>').query('.') 
       from (
        select id, 
         row_number() over (order by id) as personid, 
         person = y.i.value('(./text())[1]', 'nvarchar(4000)') 
        from ( 
         select id, x = convert(xml, '<i>' 
          + replace([source], ',', '</i><i>') 
          + '</i>').query('.') 
         from #temp 
        ) personxml 
        cross apply x.nodes('i') AS y(i) 
       ) personsplit 
      ) attributexml 
      cross apply x.nodes('i') AS y(i) 
     ) attributesplit 
    ) attributes 
) as sourcetable 
pivot (
    min(attribute) 
    for attributeid in ([1],[2],[3]) 
) as pivottable 
Смежные вопросы