T-SQL, объединяющий столбцы XML с одинаковым идентификатором

#sql #sql-server #xml #tsql #sql-server-2016

Вопрос:

Привет всем, у меня есть вопрос об объединении подобных идентификаторов, которые также имеют столбец XML.

Мои данные я пытаюсь объединить:

 _ID    _xml                                                                                              _indivisualCommaList    _eachIndividual
------ ------------------------------------------------------------------------------------------------- ----------------------- ---------------
46589  <Individual><TBS>768-hER-382</TBS><Categories /><TBS2>768-hER-382,908-YTY-354</TBS2></Individual> 768-hER-382,908-YTY-354 768-hER-382
46589  <Individual><TBS>768-hER-382</TBS><Categories /><TBS2>768-hER-382,908-YTY-354</TBS2></Individual> 768-hER-382,908-YTY-354 908-YTY-354
 

Где

_ID = INT

_xml = XML

_индивизуалькоммалист = VARCHAR(МАКС)

_eachIndividual = VARCHAR(МАКС)

Красивый (легче читаемый) XML сверху:

 <Individual>
  <TBS>768-hER-382</TBS>
  <Categories />
  <TBS2>768-hER-382,908-YTY-354</TBS2>
</Individual>

<Individual>
  <TBS>768-hER-382</TBS>
  <Categories />
  <TBS2>768-hER-382,908-YTY-354</TBS2>
</Individual>
 

XML, идентификатор и _indivisualcommerce всегда будут одинаковыми, независимо от того, сколько строк вернется обратно. Единственным уникальным столбцом будет _eachIndividual.

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

 SELECT 
  * 
FROM 
  @tblData 
WHERE 
  _ID = @AssetID 
GROUP BY 
  _ID
 

Естественно, из-за моего столбца XML я получаю ошибку:

Столбец «@tblData._xml » недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY.

Так что я действительно не уверен, что я могу сделать, чтобы объединить эти строки?

Конечный результат, которого я жду, — это:

 _ID    _xml                                                                                              _indivisualCommaList    _eachIndividual
------ ------------------------------------------------------------------------------------------------- ----------------------- -----------------------
46589  <Individual><TBS>768-hER-382</TBS><Categories /><TBS2>768-hER-382,908-YTY-354</TBS2></Individual> 768-hER-382,908-YTY-354 768-hER-382,908-YTY-354
 

ИТАК, возможно ли это сделать?

Комментарии:

1. «XML, идентификатор и _indivisualCommaList всегда будут одинаковыми» — затем объедините _eachIndividual только по идентификатору и присоедините его обратно.

2. @Serg Не против показать пример этого?

3. Смотрите ответ.

4. XML нужен корневой узел, что вам здесь нужно?

Ответ №1:

Если я все правильно понял и для данного _ID только _eachIndividual меняется

 select top(1) with ties t._ID, t._xml, t._indivisualCommaList, t2.x as _eachIndividual
from tbl t
join (select _ID, string_agg(_eachIndividual, ',') x
      from tbl
      group by _ID) t2 on t._ID = t2._ID
order by row_number() over(partition by t._ID order by t._ID)
 

Использование for xml path агрегации в более старых версиях

 select top(1) with ties t._ID, t._xml, t._indivisualCommaList,
   stuff((select  ','   t2._eachIndividual 
      from tbl t2
      where t2._ID = t._ID
      for xml path ('')), 
    1,1, '') _eachIndividual 
from tbl t
order by row_number() over(partition by t._ID order by t._ID)
 

Комментарии:

1. Спасибо за пример. Я не могу использовать string_agg с моей версией SQL.

2. Сделайте это с for xml path альтернативой. Добавил и этот запрос.

3. Кажется, работает хорошо. Тем не менее, я пытался не выполнять запрос, используя ТОП-1 .

4. Что top(1) конкретно не так с top(1) with ties этим?

Ответ №2:

Решение (с ужасной производительностью) без string_agg должно быть:

 SELECT 
    dataA._id, 
    dataA._xml, 
    dataA._individualCommaList,
    CONCAT(dataA._eachIndividual,',',dataB._eachIndividual) as _eachIndividual
FROM data dataA
JOIN data dataB ON dataA._id = dataB._id AND dataA._eachIndividual != dataB._eachIndividual
WHERE dataA._individualCommaList = CONCAT(dataA._eachIndividual,',',dataB._eachIndividual)

 

db<>скрипка

ПРИСОЕДИНИТЕ таблицу к себе, чтобы собрать необходимые данные в одну строку, но только присоединитесь к разным индивидуалам.
Предложения WHERE гарантируют, что будет сохранена запись в правильном порядке.
Альтернативно, вы могли бы использовать LIKE, чтобы сохранить строку из первого(?) индивидуала в списке.

Комментарии:

1. Это, кажется, работает, но, похоже, возникают проблемы, если в столбце _eachIndividual есть НУЛЬ или пробел .

2. Также кажется, что если строк больше 2, это ничего не показывает?