在 SQL Server XML 列中,如何验证相同的值是不是存在于多行中

Posted

技术标签:

【中文标题】在 SQL Server XML 列中,如何验证相同的值是不是存在于多行中【英文标题】:In SQL Server XML column how do I verify whether same value is present in more than one rows or not在 SQL Server XML 列中,如何验证相同的值是否存在于多行中 【发布时间】:2021-03-10 17:40:12 【问题描述】:

在 SQL Server XML 列中,如何验证相同的值是否存在于多行中?

值可以是动态的 - 它不是固定的。请参考下表,其中 Id 列为主键,ExtendedData 列中的 Tag 值可能超过 1 行。

查询INSERT记录到表中

DECLARE @Table1 TABLE (Id BIGINT, AccountNumber int,ExtendedData XML)

INSERT INTO @Table1 (Id,AccountNumber,ExtendedData) VALUES
(1, 14, '<ExtendedData> <Data>      <POLICYNBR>131313</POLICYNBR>      <ACCOUNTNBR>GGAHAHA</ACCOUNTNBR>      <ID>29499785613092400202</ID>  </Data></ExtendedData>'),
(2, 14, '<ExtendedData> <Data>      <POLICYNBR>131313</POLICYNBR>       <ACCOUNTNBR>GGAHAHA</ACCOUNTNBR>        <ID>29499785613092400202</ID>   </Data></ExtendedData>'),
(3, 14, '<ExtendedData> <Data>      <POLICYNBR>54555</POLICYNBR>        <ACCOUNTNBR>GGAHAHA</ACCOUNTNBR>        <ID>123485613092400202</ID>     </Data></ExtendedData>'),
(4, 13, '<ExtendedData> <Data>      <POLICYNBR>54555</POLICYNBR>        <ACCOUNTNBR>GGAHAHA</ACCOUNTNBR>        <ID>123485613092400202</ID> </Data></ExtendedData>')

预期结果:- 如果我通过 Account id =14 那么我应该能够在响应中看到两条记录,因为对于 accountId=14 标签在 ExtendedData 列中具有相同的值。

这是我的脚本:-但它似乎不起作用,它没有给出我期望的结果。

select * from Table1 where AccountId =14 and 
ExtendedData.value('(/ExtendedData/Data/ID/text())[1]','varchar(10)') = select CAST(ExtendedData as XML).value('(/ExtendedData/Data/ID/)[1]', 'nvarchar(20)') from Table1 where ExtendedData.value('(/ExtendedData/Data/ID/text())[1]','varchar(10)')

请给我建议

表名是Table1Id 列是主键。

【问题讨论】:

在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:***.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上面#1 中的样本数据。 (4) 你的 SQL Server 版本 (SELECT @@version;) 根据建议,我添加了所有必需的详细信息。 Kumas、##1、3 和 4 不见了。 我已更新 - SQL Server 2012 ##1,3 怎么样? 【参考方案1】:

听起来你只需要一个having,在提取了相关的 id 值之后

select t.AccountId, v.ExtendedId
from Table1 t
cross apply (values(
    ExtendedData.value('(/ExtendedData/Data/ID/text())[1]','varchar(10)')
) ) v(ExtendedId)
where AccountId = 14
group by t.AccountId, v.ExtendedId
having count(*) > 1

【讨论】:

【参考方案2】:

首先是一些可重复使用的示例数据:

DECLARE @xml XML =
'<ExtendedData>
  <Data>
    <PolNbr>123999</PolNbr>
    <ActNbr>ABCZZZ</ActNbr>
    <ID>555444</ID>
  </Data>
</ExtendedData>
<ExtendedData>
  <Data>
    <PolNbr>123999</PolNbr>
    <ActNbr>ABCXXX</ActNbr>
    <ID>555667</ID>
  </Data>
</ExtendedData>
<ExtendedData>
  <Data>
    <PolNbr>123111</PolNbr>
    <ActNbr>ABCZZZ</ActNbr>
    <ID>555667</ID>
  </Data>
</ExtendedData>
<ExtendedData>
  <Data>
    <PolNbr>123113</PolNbr>
    <ActNbr>ABCXXX</ActNbr>
    <ID>555666</ID>
  </Data>
</ExtendedData>'

SELECT
  ID     = n.X.value('(ID)[1]','varchar(100)'),
  PolNbr = n.X.value('(PolNbr)[1]','VARCHAR(100)'),
  ActNbr = n.X.value('(ActNbr)[1]','varchar(100)')
FROM        (VALUES(@xml)) AS f(X)
CROSS APPLY f.X.nodes('/ExtendedData/Data') AS n(X);

注意输出:

ID       PolNbr    ActNbr
-------- --------- ----------
555444   123999    ABCZZZ
555667   123999    ABCXXX
555667   123111    ABCZZZ
555666   123113    ABCXXX

现在我们可以调整查询以识别任何重复值:

--==== ID
SELECT      ID_Duplicates = nd.X
FROM        (VALUES(@xml)) AS f(X)
CROSS APPLY f.X.nodes('/ExtendedData/Data') AS n(X)
CROSS APPLY (VALUES(n.X.value('(ID)[1]','varchar(100)'))) AS nd(X)
GROUP BY    nd.X
HAVING      COUNT(*) > 1

--==== PolNbr
SELECT      PolNbr_Duplicates = nd.X
FROM        (VALUES(@xml)) AS f(X)
CROSS APPLY f.X.nodes('/ExtendedData/Data') AS n(X)
CROSS APPLY (VALUES(n.X.value('(PolNbr)[1]','varchar(100)'))) AS nd(X)
GROUP BY    nd.X
HAVING      COUNT(*) > 1;

--==== PolNbr
SELECT      ActNbr_Duplicates = nd.X
FROM        (VALUES(@xml)) AS f(X)
CROSS APPLY f.X.nodes('/ExtendedData/Data') AS n(X)
CROSS APPLY (VALUES(n.X.value('(ActNbr)[1]','varchar(100)'))) AS nd(X)
GROUP BY    nd.X
HAVING      COUNT(*) > 1;

结果:

ID_Duplicates
------------------------------------------
555667

PolNbr_Duplicates
------------------------------------------
123999

ActNbr_Duplicates
------------------------------------------
ABCXXX
ABCZZZ

【讨论】:

艾伦,看来 OP 想要完整地比较一列中的 XML,没有任何粉碎。 感谢艾伦的回复。在我的情况下,正如我在问题中提到的那样,我需要在给定 AccountId 的 ExtendedData 列内的 标记中找到相同值的行。你能帮我吗,我怎么能根据我的表格数据来实现

以上是关于在 SQL Server XML 列中,如何验证相同的值是不是存在于多行中的主要内容,如果未能解决你的问题,请参考以下文章

如何查询 SQL Server XML 列中的值

动态获取 SQL Server 中不同列中的 XML 数据类型值

如何从 SQL Server 中的 XML 元素获取特定属性

SQL Server 中的 XML 列比较

如何为 SQL Server(Windows 身份验证)配置 Spring XML?

如何获取列中值的不同百分比并将它们相加以分配到新的 SQL 列中?