【问题标题】:T-SQL combining XML columns with same IDT-SQL 组合具有相同 ID 的 XML 列
【发布时间】:2021-10-21 07:31:49
【问题描述】:

大家好,我有一个关于组合同样具有 XML 列的类似 ID 的问题。

我正在尝试合并的数据:

_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

_indivisualCommaList = VARCHAR(MAX)

_eachIndividual = VARCHAR(MAX)

上面的漂亮(更容易阅读)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>

无论返回多少行,XMLID_indivisualCommaList 都将始终相同。唯一唯一的列是 _eachIndividual

所以我尝试使用以下查询将类似的 ID 组合在一起

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

那么,这样可以吗?

【问题讨论】:

  • “XML、ID 和 _indivisualCommaList 将始终相同” - 然后仅按 ID 聚合 _eachIndividual 并将其加入。
  • @Serg Mind 展示了一个例子?
  • 查看答案。
  • XML需要一个根节点,这里要什么?

标签: sql sql-server xml tsql sql-server-2016


【解决方案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)

【讨论】:

  • 感谢您的示例。我的 SQL 版本无法使用 string_agg
  • 也可以使用for xml path。也添加了这个查询。
  • 似乎运作良好。但是,我试图不使用 TOP 1 进行查询。
  • 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<>fiddle

将表加入到自身中以将必要的数据放入一行,但只加入不同的个人。
WHERE 子句确保保留正确顺序的记录。
或者,您可以使用 LIKE 来保留列表中第一个(?)个人的行。

【讨论】:

  • 这似乎可行,但如果 _eachIndividual 列中有 NULL 或空白,似乎会出现问题。
  • 似乎如果有超过 2 行它什么也没有显示?
猜你喜欢
  • 2016-05-12
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 2021-12-29
  • 1970-01-01
相关资源
最近更新 更多