Reputation: 45
In a SQL Server XML column, how do I verify whether same value is present in more than one rows or not?
Value could be dynamic - it's not fixed. Kindly refer to the table shown below, where Id column is Primary Key and in ExtendedData column Tag value could be in more than 1 rows.
Query to INSERT record into table
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>')
Expected result :- If I pass Account id =14 then I should be able to see two records in the response, because both for the accountId=14 tag has same value in ExtendedData column.
This is my script : - But it seems to be its not working , it not giving the result which I am expecting.
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)')
Please suggest me
Table name is Table1
, and Id
column is the primary key.
Upvotes: 0
Views: 96
Reputation: 71579
Sounds like you just need a having
, after having pulled out the relevant id value
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
Upvotes: 1
Reputation: 7918
First for some re-usable sample data:
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);
Note the output:
ID PolNbr ActNbr
-------- --------- ----------
555444 123999 ABCZZZ
555667 123999 ABCXXX
555667 123111 ABCZZZ
555666 123113 ABCXXX
Now we can adjust our query to identify any duplicate value:
--==== 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;
Results:
ID_Duplicates
------------------------------------------
555667
PolNbr_Duplicates
------------------------------------------
123999
ActNbr_Duplicates
------------------------------------------
ABCXXX
ABCZZZ
Upvotes: 0