1

I've looked around, but can't find my specific issue.

I have XML data that looks like this in a SQL column:

<root>
   <role value="Alpha" id="1" />
   <role value="Gamma" id="2" />
   <role value="Beta" id="3" />
</root>
<root>
   <role value="Omega" id="1" />
   <role value="Delta" id="2" />
   <role value="Charlie" id="3" />
</root>

The id for this record is 1

I need the output to resemble this:

Id  Role1         Role2        Role3
====================================
1   Alpha         Gamma        Beta
1   Omega         Delta        Charlie

Any thoughts? The best I can do is return each line as it's own record and field using

select
      id,
      (SELECT ent.value('@value', 'varchar(32)')
       WHERE ent.value('@id', 'int') = '1') 
      as RoleName1,
      (SELECT ent.value('@value', 'varchar(32)')
       WHERE ent.value('@id', 'int') = '2') 
      as RoleName2,
      (SELECT ent.value('@value', 'varchar(32)')
       WHERE ent.value('@id', 'int') = '3') 
      as RoleName3
from 
      MyTable cross APPLY

      Roles.nodes('/root') AS Roles(pref)
      cross apply pref.nodes('./role') AS role(ent)

where id = 1

It produces:

id  RoleName1   RoleName2   RoleName3
1   Alpha   (null)  (null)
1   (null)  Gamma   (null)
1   (null)  (null)  Beta
1   Omega   (null)  (null)
1   (null)  Delta   (null)
1   (null)  (null)  Charlie

1 Answer 1

2

The problem is that you are breaking out the next level of nodes, you don't want to do this as you want to keep them all on the same row. Also, you are using SQL to filter, when you can do it much easier in XQuery.

Instead, use .value with an XQuery filter

SELECT
      id,
      r.roles.value('(role[@id = "1"]/@value)[1]', 'varchar(32)') AS RoleName1,
      r.roles.value('(role[@id = "2"]/@value)[1]', 'varchar(32)') AS RoleName2,
      r.roles.value('(role[@id = "3"]/@value)[1]', 'varchar(32)') AS RoleName3
FROM MyTable t
CROSS APPLY t.Roles.nodes('/root') AS r(roles)
WHERE id = 1;

db<>fiddle

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.