Динамические столбцы SQL из столбца nvarchar, содержащего xml - PullRequest
3 голосов
/ 27 октября 2011

Мне дали таблицу со следующими столбцами и некоторыми примерами данных:

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>

И мне нужно запросить его, чтобы получить такой результат:

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

Предполагается, что поле xml должно быть правильно сформировано и соответствовать схеме, даже если это nvarchar, а не тип xml. Однако значения атрибута Name заранее неизвестны.

Я использую SQL Server 2008. При необходимости я могу использовать хранимый процесс, но я ищу решение, которое может избежать этого, а также избежать динамического SQL. Разве нельзя написать такой запрос?

Если хранимые процедуры или динамический sql являются единственным способом, я открыт для решения, использующего это.

1 Ответ

3 голосов
/ 27 октября 2011
-- 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...