在 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 列中,如何验证相同的值是不是存在于多行中的主要内容,如果未能解决你的问题,请参考以下文章