T-SQL на XML (с использованием XQuery) - PullRequest
0 голосов
/ 13 сентября 2010

У меня ниже XML

<myroot>
<scene>
<sceneId>983247</sceneId>
<item>
<coordinates>
<coordinate>0</coordinate>
<coordinate>1</coordinate>
<coordinate>2</coordinate>
<coordinate>3</coordinate>
</coordinates>
<Values>
<Value>34</Value>
<Value>541</Value>
<Value>255</Value>
<Value>332</Value>
</Values>
</item>
</scene>
</myroot>

Как получить с помощью TSQL следующий результат:

Col1 Col2
0    34    
1    541
2    255
3    332

Спасибо

M

Ответы [ 2 ]

1 голос
/ 13 сентября 2010

Это выражение XPath 2.0:

/myroot/scene/item/
   string-join(for $pos in (0 to max(*/count(*)))
               return string-join(for $col in (1 to max(count(*)))
                                  return if ($pos=0)
                                         then concat('Col',$col)
                                         else *[$col]/*[$pos],
                                  ' '),
               '&#xA;')

Вывод:

Col1 Col2
0 34
1 541
2 255
3 332
0 голосов
/ 14 сентября 2010

Вот мой подход к XML-нубам.

Если вы доверяете только последовательности элементов, а не значениям координат, являющимся последовательностью:

select
  coordinate  = max(case when element = 'coordinate' then elemval end)
, value       = max(case when element = 'Value' then elemval end)
from (
  select 
    element   = row.value('local-name(.)','varchar(32)')
  , elemval   = row.value('.','int')
  , position  = row.value('for $s in . return count(../*[. << $s]) + 1', 'int')
  from @xml.nodes('/myroot/scene/item/*/*') a (row)
  ) a
group by position

Альтернативно записывается как два .nodes() и JOIN (вы поняли).

Если вы полагаете, что нумерация координат является последовательностью, начинающейся с нуля:

select 
  coordinate = row.value('for $s in . return count(../*[. << $s]) + 1', 'int')
             - 1
, value      = row.value('.','int')
from @xml.nodes('/myroot/scene/item/Values/*') a (row)

Если вы доверяете нумерации координат только как последовательности, но из произвольного начального числа:

select 
  coordinate = row.value('for $s in . return count(../*[. << $s]) + 1', 'int')
             + row.value('(/myroot/scene/item/coordinates/coordinate)[1]','int')
             - 1
, value      = row.value('.','int')
from @xml.nodes('/myroot/scene/item/Values/*') a (row)

Пути могут быть сокращены:

  • /myroot/scene/item/*/* -> //item/*/*
  • /myroot/scene/item/Values/* -> //Values/*
  • /myroot/scene/item/coordinates/coordinate -> //coordinate

Но я не знаю мудрости этого в любом случае.

//item/*/*, вероятно, можно сделать более конкретным, чтобы он включал только coordinate и Value краевые узлы, но я не знаю синтаксис.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...