SQL Server XML XQuery select where clause attribute - sql-server

I have a table with the following content
Id | Guid | XmlDefinitionId
1 | 5a0bfc84-13ec-4497-93e0-655e57d4b482 | 1
2 | e28e786b-0856-40b6-8189-0fbd68aa3e45 | 1
And in another table the following XML structure stored:
<ActionActivity DisplayName="DisplayName 1" IsSkipped="False" Id="5a0bfc84-13ec-4497-93e0-655e57d4b482">...</ActionActivity>
<p:Sequence DisplayName="Prerequisites">
<ActionActivity DisplayName="Inner DisplayName 1" IsSkipped="False" Id="e28e786b-0856-40b6-8189-0fbd68aa3e45">...</ActionActivity>
</p:Sequence>
<ActionActivity DisplayName="DisplayName 2" IsSkipped="False" Id="dcc936dd-73c9-43cc-beb4-c636647d4851">...</ActionActivity>
The table containing the XML have the following structure:
Id | XML
1 | (XML Structure defined above here)
Based on the Guid I want to show the displayname. At the moment I have the following query that returns null at the moment. Later I want for every guid from the first table show the displayname.
SELECT
Workflow
,CAST(Workflow as XML).value('data(//ActionActivity[#Id="73c9-43cc-beb4-c636647d4851"])[1]', 'nvarchar(50)') as displayname
FROM SerializedData
Anyone ideas to show the displayname with a sql query?

Assuming that the XML stored in XML typed column, you can do this way -otherwise you'll need to CAST the column to XML- :
SELECT
g.guid, x.display_name
FROM GuidTable g
INNER JOIN
(
SELECT
t.id as 'xml_id'
, c.value('#Id', 'varchar(max)') as 'guid'
, c.value('#DisplayName', 'varchar(max)') as 'display_name'
FROM XmlTable t
CROSS APPLY t.xml.nodes('//ActionActivity') as aa(c)
) x on x.guid = g.guid and x.xml_id = g.xmldefinitionid
Basically, above query shred the XML at ActionActivity node. And then joins shredded data with GuidTable on guid and xmldefinitionid columns.
output :
SQL Fiddle

Related

How to print out multiple rows of XML values using SQL

I have a database called Companies.
There is a table within Companies called Employees.
Within Employees there is a column that contains an XML response. The Column is called Data.
The XML Response looks like this
<Employee>
<Tenure>7</Tenure>
<Age>55</Age>
<OfficesVisited>
<int>1132</int>
<int>3345</int>
<int>7534</int>
</OfficesVisited>
</Employee>
What I would like my sql query to print out is:
OfficesVisited
1132
3345
7534
What I am currently getting is 113233457534
I am using this sql query:
use Companies
SELECT Employees.Data.query('(/Employee/OfficesVisited/int/text())') as OfficesVisited
FROM Employees
Where Employee.Employee_ID = 65035277
I've tried using OUTER APPLY and CROSS APPLY and I can get it into 3 rows but all three rows look like the above.
Can Anyone help?
Thanks!
Please try the following. It shows how to use .nodes() and .value() XML methods correctly.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, [data] XML);
INSERT INTO #tbl ([data]) VALUES
(N'<Employee>
<Tenure>7</Tenure>
<Age>55</Age>
<OfficesVisited>
<int>1132</int>
<int>3345</int>
<int>7534</int>
</OfficesVisited>
</Employee>')
, (N'<Employee>
<Tenure>77</Tenure>
<Age>58</Age>
<OfficesVisited>
<int>7777</int>
<int>8888</int>
</OfficesVisited>
</Employee>')
, (N'<Employee>
<Tenure>90</Tenure>
<Age>50</Age>
<OfficesVisited>
<int>1111</int>
</OfficesVisited>
</Employee>');
-- DDL and samplex data population, end
SELECT c.value('(./text())[1]','INT') AS OfficesVisited
FROM #tbl AS tbl
CROSS APPLY tbl.[data].nodes('/Employee/OfficesVisited/int') AS t(c)
WHERE id IN (1,2);
Output
+----------------+
| OfficesVisited |
+----------------+
| 1132 |
| 3345 |
| 7534 |
| 7777 |
| 8888 |
+----------------+

TSQL Distinct within subquery using xml

I have the following table structure:
Table1 - List of Possible Region/Market Options
Region | Market
--------+----------------
EMEA | London
NA | Omaha
EMEA | Another City
Table2 - Holds the Markets that were selected as impacts
RequestID | Market
------------+----------------
123 | London
123 | Omaha
456 | Another City
Within my stored procedure, I am trying to create a distinct list of Region/Markets that are impacted based on Table2. The end result will be a distinct list of regions with all of the markets within them that are impacted.
In this case, there are two impacts from the EMEA region but I wouldn't want EMEA to show up twice.
When I was doing this on a single request, I was able to create a temp table and insert the data into it and then accomplish what I needed to do. However, this is pulling all of the results and I need to do this within the query and I am not sure how..
This code works fine if I wasn't getting the distinct data from it. Otherwise, it throws the error:
The xml data type cannot be selected as DISTINCT because it is not comparable.
Is there another way I can accomplish this within a sub-query/sub-select?
...
(SELECT DISTINCT
region,
(SELECT m.market
FROM dbo.bs_ToolRequests_MarketOptions AS m
INNER JOIN dbo.BS_ToolRequests_ImpactedMarkets AS ma ON ma.market = m.market
WHERE m.region = mo.region
AND ma.requestID = t.requestID
FOR XML PATH ('options'), TYPE, ELEMENTS, ROOT ('markets'))
FROM
dbo.BS_ToolRequests_MarketOptions AS mo
FOR XML PATH ('regions'), TYPE, ELEMENTS, ROOT ('impactedMarkets')),
Expected result:
<impactedMarkets>
<regions>
<region>EMEA</region>
<markets>
<options>
<market>London</market>
</options>
<options>
<market>Another City</market>
</options>
</markets>
</regions>
</impactedMarkets>
Probably you need to use DISTINCT keyword in the SELECT statement of derived table
...
(SELECT region,
(SELECT m.market
FROM dbo.bs_ToolRequests_MarketOptions AS m
INNER JOIN dbo.BS_ToolRequests_ImpactedMarkets AS ma ON ma.market = m.market
WHERE m.region = mo.region
AND ma.requestID = t.requestID
FOR XML PATH ('options'), TYPE, ELEMENTS, ROOT ('markets'))
FROM
(SELECT DISTINCT region FROM dbo.BS_ToolRequests_MarketOptions) AS mo
FOR XML PATH ('regions'), TYPE, ELEMENTS, ROOT ('impactedMarkets')),

Generating xml from SQL Server 2008

For a given claim I have 3 diagnosis codes. Currently while generating xml from SQL Server, I get 3 branches one for each diagnosis code with same claim id as displayed in below output. But I need a way out so that all the 3 diagnosis code can be clubbed with the associated claim id and produce desire result snippet.
Select statement is :
select *
from sandbox.dbo.testing
WHERE claimID = 20
FOR XML auto,ELEMENTS
The output is
claimID diagnosis
20 v234
20 v24
20 v256
The XML generated is:
<sandbox.dbo.testing>
<claimID>20</claimID>
<diagnosis>v234</diagnosis>
</sandbox.dbo.testing>
<sandbox.dbo.testing>
<claimID>20</claimID>
<diagnosis>v24</diagnosis>
</sandbox.dbo.testing>
<sandbox.dbo.testing>
<claimID>20</claimID>
<diagnosis>v256</diagnosis>
</sandbox.dbo.testing>
But need the result in below form
<sandbox.dbo.testing>
<claimID>20</claimID>
<diagnosis>v234</diagnosis>
<diagnosis>v24</diagnosis>
<diagnosis>v256</diagnosis>
</sandbox.dbo.testing>
Fetch the rows in a subquery and hard code or use a parameter for the claimID in the main query.
select 20 as claimID,
(
select diagnosis
from sandbox.dbo.testing
where claimID = 20
for xml path(''), type
)
for xml path('sandbox.dbo.testing')
Use Xml Path() and Root
SELECT *
FROM sandbox.dbo.testing
WHERE claimID = 20
FOR xml path(''), root('sandbox.dbo.testing')

Querying XML Rows For New Non-XML Rows

Note: See this spelled out example on SQL Fiddle, or look at the code below:, as the DECLARE #XML variable examples are confusing the syntax when trying to actually obtain XML data from an XML column and intended for non-XML rows:
CREATE TABLE ##xml (
ID TINYINT IDENTITY(1,1),
Value XML
)
INSERT INTO ##xml (Value)
VALUES ('<Animals key="zoo" fish="22" dogs="0" birds="4" />')
, ('<Animals key="house" fish="0" dogs="1" birds="2" />')
, ('<Animals key="business" fish="0" dogs="0" birds="12" />')
SELECT *
FROM ##xml
SELECT nodes.child.value('key[1]', 'VARCHAR(50)')
FROM ##xml.Value.nodes('Animal') AS nodes(child)
-- Errors here, though the syntax looks correct
DROP TABLE ##xml
I'm getting the error, "Invalid column name '##xml'. The XMLDT method 'nodes' can only be invoked on columns of type xml" even though I'm trying to query the nodes of XML to produce a result like the below:
Key | Fish | Dogs | Birds
Zoo 22 0 4
House 0 1 2
Business 0 0 12
Note, if I change the syntax of the FROM statement to point to the specific column (Value), I receive other errors about Value not being a recognized built-in function name.
Do it like this:
SELECT nodes.child.value('#key','varchar(100)')
FROM ##XML a
CROSS APPLY a.value.nodes('/Animals') AS nodes(child)

SQL View where rows not mapped

Basically what I'm trying to figure out is,
Say I have
table 1tbl1
ID | Name
and table2tbl2
ID | Name
Then I have a mapping table mt
ID | tbl1ID | tbl2ID
Data really isn't important here, and these tables are examples.
How to make a view that will grab all the items in tbl1 that aren't mapped to mt.
I'm using Microsoft SQL-server 2008 by the way.
CREATE VIEW v_unmapped
AS
SELECT *
FROM tbl1
WHERE id NOT IN
(
SELECT tbl1Id
FROM mt
)

Resources