Вопрос о расположении узла MS SQL 2005 "For XML Path" - PullRequest
0 голосов
/ 26 марта 2009

У меня есть следующий запрос

Select field1 as 'node1/field1',
       field2 as 'node1/field2',
  (Select field3 as 'child1/field3',
          field4 as 'child1/field4'
   From table2
   FOR XML PATH(''),TYPE,Elements)
From Table1 FOR XML PATH('Root'),Elements

Это производит:

<Root>
  <node1>
    <field1>data1</field1>
    <field2>data2</field2>
  </node1>
   <child1>
     <field3>data3</field3>
     <field4>data4</field4>
   </child1>
   <child1>
     ...   
</Root>

Я бы хотел, чтобы дочерние узлы были частью узла1, а не отдельным узлом ниже.

<Root>
  <node1>
    <field1>data1</field1>
    <field2>data2</field2>
    <child1>
       <field3>data3</field3>
       <field4>data4</field4>
    </child1>
    <child1>
      ...
 </node1>
 <node1>
   ...
</Root>

Я пытался поместить node1 в подзапрос PATH

FOR XML PATH('node1'),TYPE,Elements)

или добавление префикса к именам полей подзапроса с помощью node1

Select field3 as 'node1/child1/field3',

но оба создают новый элемент node1 для подзапроса.

Кто-нибудь знает, как мне это сделать?

Спасибо

Ответы [ 4 ]

0 голосов
/ 28 марта 2009

Это может иметь больше смысла, если вы публикуете некоторые образцы данных, а не используете node1, field1, child1 и т. Д. И объясняете, из каких таблиц поступают данные.

XML является иерархическим по своей природе. Вы не можете произвольно запускать новые узлы, которые не связаны с другими узлами под корнем, что, как кажется, вы пытаетесь сделать.

Все в пределах <node1> .. to .. </node1> относится к одной записи и данным, сгенерированным ее подзапросами. Следующая последовательность узлов будет копировать структуру как <node2> .. to .. </node2> для следующей записи.

Если вам нужно больше подзапросов для каждого узла, просто напишите каждый из них в SQL со своим собственным FOR XML PATH('SubNodeName')

Опубликуйте свой XSD или образец кода XML, и я посмотрю, смогу ли я выяснить, что вы пытаетесь сделать.

0 голосов
/ 27 марта 2009

Я не проделал большую работу с T-SQL и FOR XML, но я обошел похожую проблему, вызывая часть запроса FOR XML после каждого подзапроса, как показано ниже, и используя идентификатор PATH установить узлы:

SELECT field1 as "Field1",
    field2  as "Field2",
    (select
        field3 as "Field3",
        field4 as "Field4"

        from table2 t2 inner join 
        tlink tl on tl.id = t2.id inner join
        table2 on t2.id = tl.id
        group by field3, field4
        FOR XML PATH ('Child'), type
        ) 

from table2 t2 
group by field1, field2
FOR XML PATH('Node'), ROOT('Root')

это возвращает:

<Root>
  <Node1>
    <Field1>data1</Field1>
    <Field2>data2</Field2>
    <Child1>
      <Field3>data3</Field3>
      <Field4>data4</Field4>
    </Child1>
  </Node1>
  <Node2>
    <Field1>data1.2</Field1>
    <Field2>data2.2</Field2>
    <Child2>
      <Field3>data3.2</Field3>
      <Field4>data4.2</Field4>
    </Child2>

...
  </Node2>

...
</Root>

Как упоминал Андомар, вам нужно убедиться, что ваши данные правильно объединены.

Я также включил предложение Group By, чтобы убедиться, что данные не «сбиваются с пути». У меня была проблема с репликацией данных подзапроса в качестве дочерних для каждой записи во внешнем запросе (под каждым узлом было несколько дочерних элементов, связанных с количеством узлов). Я уверен, что есть простое объяснение, но я был работая в сжатые сроки, когда я сделал это и никогда не возвращался, чтобы проверить ...

Если это неправильное использование или кто-то может пролить свет на повторяющиеся группы, укажите это, и я отредактирую ...

0 голосов
/ 27 марта 2009

Мой первый пример запроса был не совсем верным, как вы указали. Вот более точный пример запроса.

Select field1 as 'node1/field1',       
       field2 as 'node1/field2',  
  (Select field3 as 'child1/field3',          
        field4 as 'child1/field4'   
   From table2   
   Where table1.ID = table2.ID
   FOR XML PATH(''),TYPE,Elements),
       field5 as 'node2/field5',
       field6 as 'node2/field6'
From table1 FOR XML PATH('Root'),Elements

Который производит:

<Root>
  <node1>
    <field1>data1</field1>
    <field2>data2</field2>
  </node1>   
  <child1>     
    <field3>data3</field3>
    <field4>data4</field4>
  </child1>
  <node2>
    <field5>data5</field5>
    <field6>data6</field6>
  </node2>
</Root>

field5 и field6 - это поля из внешнего запроса, но они находятся в другом пути к узлу, node2. Вот почему я не могу иметь PATH ('узел') во внешнем запросе. Внешние поля запроса используются во многих различных путях узла в Root. Мне нужно, чтобы подзапрос повторился под узлом 1, и есть другие подзапросы, которые нужно вернуть под узлом 2, узлом 3 ...
Я надеюсь, что я понимаю. Это мой первый пост, и в следующий раз я опишу лучший пример запроса.

Спасибо за ответы.

Dirk

0 голосов
/ 27 марта 2009

Вы должны сообщить SQL Server, как связаны таблица1 и таблица2. Исходя из вашего ответа ниже, я думаю, что что-то вроде этого может помочь:

select 
    table1.field1 as 'Node1/Field1'
,   table2.field1 as 'Node1/Child1/Field1'
,   table1.field2 as 'Node2/Field2'
from table1
left join table2 on table1.id = table2.table1id
for xml PATH(''), ROOT('Root')

Это должно создать XML как:

<Root>
    <Node1>
        <Field1>Value</Field1>
        <Child1>
            <Field1>Value</Field1>
        </Child1>
    </Node1>
    <Node2>
        <Field2>Value</Field2>
    </Node2>
</Root>
...