Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Conversione di stringhe delimitate da virgole in più colonne nel server sql

Puoi vederlo funzionare su SQL Fiddle:http://sqlfiddle.com/#!3/ 8c3ee/32

Ecco il succo:

with parsed as (
  select
  commasepa,
  root.value('(/root/s/col[@name="X"])[1]', 'varchar(20)') as X,
  root.value('(/root/s/col[@name="Y"])[1]', 'varchar(20)') as Y,
  root.value('(/root/s/col[@name="Z"])[1]', 'varchar(20)') as Z,
  root.value('(/root/s/col[@name="A"])[1]', 'varchar(20)') as A,
  root.value('(/root/s/col[@name="B"])[1]', 'varchar(20)') as B,
  root.value('(/root/s/col[@name="C"])[1]', 'varchar(20)') as C,
  root.value('(/root/s/col[@name="D"])[1]', 'varchar(20)') as D
FROM
(
select
   commasepa,
   CONVERT(xml,'<root><s><col name="' + REPLACE(REPLACE(COMMASEPA, '=', '">'),',','</col></s><s><col name="') + '</col></s></root>') as root
FROM
  samp
) xml
)
update 
  samp
  set
  samp.x = parsed.x,
  samp.y = parsed.y,
  samp.z = parsed.z,
  samp.a = parsed.a,
  samp.b = parsed.b,
  samp.c = parsed.c,
  samp.d = parsed.d
from
  parsed
where
  parsed.commasepa = samp.commasepa;

Divulgazione completa - Sono l'autore di sqlfiddle.com

Funziona convertendo prima ogni stringa commasepa in un oggetto XML simile a questo:

<root>
 <s>
  <col name="X">1</col>
 </s>
 <s>
  <col name="Y">2</col>
 </s>
  ....
</root>

Una volta che ho la stringa in quel formato, utilizzo le opzioni xquery supportate da SQL Server 2005 (e versioni successive), che è il .value('(/root/s/col[@name="X"])[1]', 'varchar(20)') parte. Seleziono ciascuna delle potenziali colonne individualmente, in modo che vengano normalizzate e popolate quando disponibili. Con quel formato normalizzato, definisco il set di risultati con una Common Table Expression (CTE) che ho chiamato "analizzato". Questo CTE viene quindi unito nuovamente nell'istruzione di aggiornamento, in modo che i valori possano essere inseriti nella tabella originale.