Разрежьте XML на несколько строк в SQL - PullRequest
0 голосов
/ 16 апреля 2019

Мне нужно уничтожать XML-документ каждые две недели.Он соответствует стандарту NEMSIS 2 , и у меня есть совместимая база данных, созданная для хранения информации.Я успешно создал запрос для импорта всех данных «один к одному», но у меня возникли проблемы с измельчением данных «один ко многим».

Использование этих демонстрационных данных:

declare @x xml  
set @x =  
'<EMSDataSet>  
    <Header>  
    <D01_01>abc</D01_01>  
        <Record>  
            <E01>  
                <E01_01>12345</E01_01>  
                <E01_02>678</E01_02>  
            </E01>  
            <E02>  
                <E02_01>123</E02_01>  
                <E02_09>295</E02_09>  
                <E02_09>296</E02_09>  
            </E02>  
        </Record>
        <Record>
            <E01>
                <E01_01>67890</E01_01>
                <E01_02>678</E01_02>
            </E01>
            <E02>
                <E02_01>123</E02_01>
                <E02_09>295</E02_09>                
            </E02>
        </Record>  
    </Header>  
</EMSDataSet>'  

Этот запрос правильно возвращает правильное значение 01_01 и первое значение 02_09.Однако, поскольку Value () может возвращать только одиночный тег, я могу получить только первое значение:

Query:  
select  
    t.c.value('(E01/E01_01)[1]','varchar(max)') e01_01  
   ,t.c.value('(E02/E02_09)[1]','varchar(max)') e02_09  
from @x.nodes('EMSDataSet/Header/Record') t(c)  

Returns:  
e01_01     e02_09  
------     ------  
 12345        295  

Этот запрос возвращает оба значения 02_09 в своих строках, но несоответствующие значения 01_01:

Query:  
select  
    t2.c.value('.','varchar(max)') e02_09  
from @x.nodes('EMSDataSet/Header/Record/E02/E02_09') t2(c)  

Returns:  
e02_09  
 -----  
   295  
   296  

Мне нужно объединить результаты и извлечь оба значения значения 02_09 со значением 01_01, повторенным в каждой строке.Значение 01_01 будет действовать как внешний ключ в базе данных, ссылаясь на конкретный уникальный инцидент.

e01_01     e02_09  
------     ------  
 12345        295  
 12345        296  

Похоже, что для этого, вероятно, требуется использование метода Nodes () ивозможно Join , но я не могу понять синтаксис, чтобы получить повторяющееся значение для одного значения 01_01 для каждого значения 02_09.

Эти вопросы / ответы позволили мне зайти так далеко:

Извлечь все дочерние узлы от родительского узла xml-sql-server
Возвращение нескольких строк из запроса столбца XML в SQL Server 2008
T-SQL Shred XML-узлов второго уровня на несколько строк
Shred XML для каждой строки в таблице SQL

РЕДАКТИРОВАТЬ: Я попытался следовать код после раннего успеха.Однако вместо того, чтобы вернуть правильные 36 строк (35 записей с повторением для двойного значения e02_09) из моего набора тестовых данных, он вернул 1260 записей (36 строк * 35 строк).

select *
from
    (
      select 
          t.c.value('(E01/E01_01)[1]','varchar(max)') e01_01
      from @x.nodes('EMSDataSet/Header/Record') t(c)
    ) a
    ,
    (
      select
          t2.c.value('.','varchar(max)') e02_09
      from @x.nodes('EMSDataSet/Header/Record/E02/E02_09') t2(c)
    ) b

1 Ответ

0 голосов
/ 16 апреля 2019

Лучший ответ, который я смог получить, основан на этом сообщении в блоге Адама Мачаника :

select 
    e01_01
    ,e02_09
from
    (select 
        dense_rank() over (order by b_node) unique_b_node
        ,c_node.value('./text()[1]','varchar(max)') e02_09

    from @x.nodes('/EMSDataSet/Header/Record') b(b_node)
    cross apply b.b_node.nodes('./E02/E02_09') c(c_node)
    ) a
join
    (select
        dense_rank() over (order by b2.b_node) unique_b_node
        ,c_node.value('text()[1]','varchar(max)') e01_01
    from @x.nodes('/EMSDataSet/Header/Record') b2(b_node)
    cross apply b2.b_node.nodes('./E01/E01_01') c2(c_node)
    ) b
on a.unique_b_node = b.unique_b_node
...