2016-08-24 5 views
1

Использование SQL Server 2012. У меня есть таблица, содержащая идентификатор группы и небольшие фрагменты XML. Вот пример:Группа данных столбца XML

CREATE TABLE temp (
    GroupId [int] NOT NULL, 
    RawXml [xml] NULL 
) 

INSERT INTO temp VALUES (1, '<Item><Criteria Type="State" Values="CA"/><Criteria Type="State" Values="TX"/><Criteria Type="State" Values="FL"/></Item>') 
INSERT INTO temp VALUES (1, '<Item><Criteria Type="Manager" Values="Tim"/></Item>') 
INSERT INTO temp VALUES (2, '<Item><Criteria Type="Name" Values="Walters"/></Item>') 
INSERT INTO temp VALUES (2, '<Item><Criteria Type="Manager" Values="Tim"/></Item>') 

То, что я хочу сделать, это сгруппировать фрагменты XML вместе с GroupID сформировать больший XML документ, так что конечный результат структурирован следующим образом:

<Parent> 
    <Group GroupId="1"> 
     <Item> 
      <Criteria Type="State" Values="CA"/> 
      <Criteria Type="State" Values="TX"/> 
      <Criteria Type="State" Values="FL"/> 
     </Item> 
     <Item> 
      <Criteria Type="Manager" Values="Tim"/> 
     </Item> 
    </Group> 
    <Group GroupId="2"> 
     <Item> 
      <Criteria Type="Name" Values="Walters"/> 
     </Item> 
     <Item> 
      <Criteria Type="Manager" Values="Tim"/> 
     </Item> 
    </Group> 
</Parent> 

I боюсь, единственное решение состоит в том, чтобы объединить содержимое столбца XML сначала с использованием некоторого типа string concatenation method, а затем с помощью оператора выбора FOR XML, но я считаю, что это будет слишком медленным для моего приложения. Я что-то упускаю, и есть простой способ группировать XML-данные таким образом или связывать строки единственным моим выбором.

+0

Почему расщепление xml помещает весь xml в одну строку. Будет легко разобрать –

+0

Вы проповедуете хор. Честно говоря, я связан каким-то унаследованным кодеком/данными приложения, и это карты, которые я получил. Возможность конвертировать то, как данные уже сохраняются, является опцией, но я стараюсь избегать ее в настоящий момент. – Stigz

+0

Это хороший вопрос! Особенно полезен тестовый код, copy'n'pasteable и ожидаемый результат! +1 – Shnugo

ответ

2

Конечно, есть более простой способ:.

declare @t table (
    GroupId [int] NOT NULL, 
    RawXml [xml] NULL 
); 

INSERT INTO @t 
VALUES (1, '<Item><Criteria Type="State" Values="CA"/><Criteria Type="State" Values="TX"/><Criteria Type="State" Values="FL"/></Item>'), 
(1, '<Item><Criteria Type="Manager" Values="Tim"/></Item>'), 
(2, '<Item><Criteria Type="Name" Values="Walters"/></Item>'), 
(2, '<Item><Criteria Type="Manager" Values="Tim"/></Item>'); 

select sq.GroupId as [@GroupId], 
    (
     select t.RawXml as [node()] 
     from @t t 
     where t.GroupId = sq.GroupId 
     for xml path(''), type 
    ) 
from (select distinct g.GroupId from @t g) sq 
for xml path('Group'), type, root('Parent'); 

(я заменил свой оригинальный стол с эквивалентной ТВ, потому что, ну, я не хотел, чтобы очистить базы данных таких таблиц впоследствии он Безразлично не вносите никакой разницы в отношении вопроса.)

+0

Хороший ответ, +1, только один крошечный намек: я не уверен, но я думаю, что было бы немного лучше использовать 'AS [*]' или 'AS [node()]' лучше, чем '. query() ', чтобы избежать дополнительного уровня вложенности – Shnugo

+0

@ Шнуго, я забыл, как конкретно указать этот конкретный вывод :) Действительно, согласно плану выполнения, разница огромна. Исправлено, спасибо за предложение. –

+0

Это замечательно. Спасибо. Да, 't.RawXml as [node()]' делает его намного быстрее. – Stigz

Смежные вопросы