Объедините определенный атрибут всех элементов вместе с xquery

Как я могу объединить определенный атрибут всех элементов вместе с помощью SQL XQuery?

У меня есть такая таблица:

InvoiceId   Details
---------   -----------------------------------------------------------------
1001        <Stuff Id="101" p="3" q="5"/><Stuff Id="102" q="4"/><Stuff Id="103"/>
1002        <Stuff Id="201" /><Stuff Id="202" q="2"/>

и нужен этот результат =>

InvoiceId  IdDetails
---------   ---------------------
1001        101,102,103
1002        201,202

person ARZ    schedule 29.05.2011    source источник


Ответы (3)


declare @T table(InvoiceId int, Details xml)
insert into @T
select 1001, '<Stuff Id="101" p="3" q="5"/><Stuff Id="102" q="4"/><Stuff Id="103"/>' union all
select 1002, '<Stuff Id="201"/><Stuff Id="202" q="2"/>'

select InvoiceId,
       stuff((select ','+t.n.value('@Id', 'varchar(10)')
              from Details.nodes('Stuff') as t(n) 
              for xml path('')), 1, 1, '') as IdDetails  
from @T

Только уникальные значения для Id.

select InvoiceId,
       stuff((select ','+s.id
              from Details.nodes('Stuff') as t(n)
                cross apply (select t.n.value('@Id', 'varchar(10)')) as s(id) 
              group by s.id
              for xml path('')), 1, 1, '') as IdDetails  
from @T
person Mikael Eriksson    schedule 29.05.2011
comment
огромное спасибо. теперь, как мы можем различить IdDetails в результате ?? - person ARZ; 29.05.2011

Самый простой способ - использовать REPLACE.

SELECT
   InvoiceId,
   SUBSTRING(
        REPLACE(
          REPLACE(
            CAST(Details AS nvarchar(max))
                 , '<Stuff Id="', ',')
               , '"/>', '')
             ,2, 2000000000)
FROM
   MyTable
person gbn    schedule 29.05.2011
comment
мы не можем использовать метод Replace, потому что в некоторых случаях элемент Stuff может иметь другие атрибуты! тогда как можно получить такой же результат с помощью XQuery ?! - person ARZ; 29.05.2011
comment
@ARZ: Вы знаете, как называются элементы? Это конечный список или вы хотите взять какой-нибудь старый XML и проанализировать его ...? - person gbn; 29.05.2011
comment
на самом деле это не конечный список. - person ARZ; 29.05.2011
comment
@ARZ: Итак, вы не знаете, как выглядит XML? Кроме того, я не уверен, что это правильный XML в терминах SQL Server: нет корневого элемента. Он хранится в типе XML или nvarchar? - person gbn; 29.05.2011
comment
Наконец, чтобы извлечь имена тегов, вы можете использовать этот stackoverflow.com/questions/6115397/ YMMV - person gbn; 29.05.2011

Возможно, более удачный способ - использовать функцию запроса при обработке xml вместо подзапроса и прочего. Основываясь на ответе Микаэля Эрикссона, я нашел следующее из этого вопрос, чтобы он был более быстрым и лаконичным / читаемым:

declare @T table(InvoiceId int, Details xml)
insert into @T
select 1001, '<Stuff Id="101" p="3" q="5"/><Stuff Id="102" q="4"/><Stuff Id="103"/>' union all
select 1002, '<Stuff Id="201"/><Stuff Id="202" q="2"/>'

select InvoiceId, 
    t.n.query('for $i in Stuff return concat($i/@Id, ",")').value('.', 'nvarchar(max)')
from @T
    cross apply Details.nodes('.') as t(n)

Однако результирующие строки включают в себя ограничивающие пробелы и завершающую запятую.

person Retiarius    schedule 09.01.2015