2011-06-17 6 views
4

Dans une base de données SQL Server 2008, j'ai une colonne avec plusieurs valeurs séparées par des points-virgules. Certaines valeurs contiennent des deux-points. Données-échantillon:SQL Server 2008 - diviser la colonne à valeurs multiples en lignes avec des valeurs uniques

key:value;key2:value;blah;foo;bar;A sample value:whee;others 
key:value;blah;bar;others 
A sample value:whee 

Je veux obtenir toutes les valeurs uniques de chaque ligne en rangées séparées:

key:value 
key2:value 
blah 
foo 
bar 
A sample value:whee 
others 

J'ai regardé différentes split fonctions, mais ils semblent tous faire face à Hard- chaînes codées, pas des chaînes provenant d'une colonne dans une table. Comment puis-je faire ceci?

Editer: La réponse de Thomas l'a eu! Voici était ma requête finale:

With SampleInputs As 
    (
    select distinct myColumn from [myDatabase].[dbo].myTable where myColumn != '' 
    ) 
    , XmlCte As 
    (
    Select Cast('<z>' + Replace(myColumn, ';', '</z><z>') + '</z>' As xml) As XmlValue 
    From SampleInputs As I 
    ) 
Select Distinct Y.z.value('.','nvarchar(max)') As Value 
From XmlCte 
    Cross Apply XmlValue.nodes('//z') Y(z) 

Je devine que les choses XmlValue.nodes et Y.z.value est magique. O_o

+0

Seriez-vous en mesure d'utiliser C#, ou avez-vous d'utiliser tsql? –

+0

Je préférerais que cela se fasse entièrement dans T-SQL, dans SQL Server Management Studio. –

Répondre

2
With SampleInputs As 
    (
    Select 'key:value;key2:value;blah;foo;bar;A sample value:whee;others' As [Data] 
    Union All Select 'key:value;blah;bar;others' 
    Union All Select 'A sample value:whee' 
    ) 
    , XmlCte As 
    (
    Select Cast('<z>' + Replace(I.[Data], ';', '</z><z>') + '</z>' As xml) As XmlValue 
    From SampleInputs As I 
    ) 
Select Distinct Y.z.value('.','nvarchar(max)') As Value 
From XmlCte 
    Cross Apply XmlValue.nodes('//z') Y(z) 

Mise à jour

est ici une version de ce qui précède que les poignées entités:

With SampleInputs As 
    (
    Select 'key:value;key2:value;blah;foo;bar;A sample value:whee;others' As [Data] 
    Union All Select 'key:value;blah;bar;others' 
    Union All Select 'A sample value:whee' 
    Union All Select 'A sample value:<Oops>' 
    ) 
    , XmlGoo As 
    (
    Select Cast(
      Replace(
       Replace(Cast(Z.XmlValue As nvarchar(max)), '{{', '<z>') 
       , '}}', '</z>') 
      As Xml) As Xmlvalue 
    From (
      Select Cast(
        (
        Select '{{' + Replace([Data], ';', '}}{{') + '}}' 
        From SampleInputs 
        For Xml Path(''), type 
        ) As Xml) As XmlValue 
      ) As Z 
    ) 
Select Distinct Z.data.value('.', 'nvarchar(max)') 
From XmlGoo 
    Cross Apply XmlValue.nodes('/z') Z(data) 
+0

Vous devez prendre soin de '<' et '&' dans les données si vous utilisez cette technique. –

+0

@Mikael Eriksson - Cela peut être surmonté. Ont posté une version qui permettra les symboles réservés Xml. – Thomas

+0

@Mikael Eriksson - (Évidemment, si '{' ou '}' pourrait être dans les données source, un marqueur différent devrait être utilisé.) – Thomas

3

Avec une fonction split vous utilisez croisée se:

select distinct SS.part 
from YourTable 
    cross apply dbo.SplitString(YourColumn, ';') as SS 

Ici, le SplitString prend deux arguments, la colonne de chaîne et le séparateur et a une colonne appelée part où les valeurs sont retournées.

Questions connexes