2011-10-27 3 views
3

j'ai été donné une table avec les colonnes suivantes et quelques exemples de données:colonnes dynamiques de pivot SQL sur une colonne nvarchar contenant xml

ID Title FieldsXml [nvarchar(max)] 
-- ----- ------------------------- 
1  A  <Fields><Field Name="X">x1</Field><Field Name="Y">y1</Field></Fields> 
2  B  <Fields><Field Name="Y">y2</Field><Field Name="Z">z2</Field></Fields> 
3  C  <Fields><Field Name="Z">z3</Field></Fields> 

Et je dois l'interroger pour obtenir un résultat comme celui-ci:

ID Title X Y Z 
-- ----- -- -- -- 
1  A  x1 y1 
2  B   y2 z2 
3  C    z3 

Le champ xml est censé être correctement formé et correspondre au schéma même s'il s'agit d'un type nvarchar et non de type xml. Cependant, les valeurs de l'attribut Nom ne sont pas connues à l'avance. J'utilise SQL Server 2008. Je peux utiliser un proc stocké si nécessaire, mais je cherche une solution qui peut éviter cela et éviter le SQL dynamique. Est-il impossible d'écrire une telle requête?

Si procs stocké ou SQL dynamique sont la seule façon, je suis ouvert à une solution en utilisant cela.

+0

Il n'est pas possible d'avoir un nombre dynamique/variable de colonnes sans SQL dynamique. –

Répondre

3
-- Sample data 
declare @T table 
(
    ID int, 
    Title nvarchar(10), 
    FieldsXml nvarchar(max) 
) 
insert into @T values 
(1,  'A',  '<Fields><Field Name="X">x1</Field><Field Name="Y">y1</Field></Fields>'), 
(2,  'B',  '<Fields><Field Name="Y">y2</Field><Field Name="Z">z2</Field></Fields>'), 
(3,  'C',  '<Fields><Field Name="Z">z3</Field></Fields>') 

-- Create temp table 
select T.ID, 
     T.Title, 
     TN.X.value('@Name', 'nvarchar(128)') as FieldName, 
     TN.X.value('.', 'nvarchar(max)') as FieldValue 
into #tmp  
from @T as T  
    cross apply (select cast(FieldsXml as XML)) as TX(X) 
    cross apply TX.X.nodes('/Fields/Field') as TN(X) 


declare @ColList nvarchar(max) 
declare @Sql nvarchar(max) 

-- Build column list 
select @ColList = stuff((select '], ['+FieldName 
         from #tmp 
         group by FieldName 
         for xml path('')), 1, 2, '')+']' 

-- Build query 
set @Sql = 'select * 
      from (select ID, 
         Title, 
         FieldName, 
         FieldValue 
        from #tmp 
       ) as T 
      pivot (min(FieldValue) for FieldName in (' + @ColList + ')) as P' 

exec (@Sql) 

drop table #tmp 
Questions connexes