SSRS - Conditionally select elements from XML data source - sql

I have a simple XML tree:
<manufacturer = 'Audi'>
<make = 'A4'>
<color>Black</color>
<build_date>11th May 2014</build_date>
</make>
</manufacturer>
I know I can query data using:
<Query>
<ElementPath>
manufacturer{}/make{color, build_date}
</ElementPath>
</Query>
What I'd like to do is filter the results using the date attribute. Like a SQL WHERE clause. So in this example it's cars that are built after a specified date. Is this possible?

You would need set a filter on the data set in SSRS on the Build_date Field:
http://msdn.microsoft.com/en-us/library/dd255287.aspx

Yes you can filter the result from an xml. An example to your query is as below
SELECT
[xmlField].value('(/person//firstName/node())[1]', 'nvarchar(max)') as FirstName,
[xmlField].value('(/person//lastName/node())[1]', 'nvarchar(max)') as LastName
FROM [myTable]

Related

T-SQL, get value from xml in a column

I have a table with an XML column (xmlCol) and I am trying to query a value from it.
Here's the xml.
<criteria>
<factor name="Rivers" title="Rivers">
<value dataType="Int32" value="1743" description="Wilson0" />
</factor>
<factor name="OptionalAffProperties" title="Include properties">
<value dataType="String" value="FishingModel" description="Fishing Model" />
</factor>
</criteria>
Here is a select to get the column. select xmlCol from MyTable
I am trying to return the value 1743 to a column called RiverID.
Mike
This should work:
SELECT
xmlCol.value('(//factor[#name="Rivers"]/value/#value)[1]', 'int') As RiverID
FROM
MyTable
value() Method (xml Data Type) - SQL Server | Microsoft Docs
XQuery Language Reference (SQL Server) - SQL Server | Microsoft Docs
To get the attribute value, you can query it like so:
select xmlCol.value('(/criteria/factor/value/#value)[1]', 'int') RiverID
from MyTable
You provide the xml path to the record you are looking for: (/criteria/factor/value
And then the attribute you need: /#value)[1].

Trying to access an XML node value from a table column using query in SQL Server and it always returns an empty string

Have a table called UserRequest and one column of the is XML type (column name is RequestXML). The values in RequestXML will be something like this:
<MyRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/">
<transfer>
<Field>
<fieldId>12323</fieldId>
<FieldDetails>
<RequestInfoField>
<requestDecs>Test</requestDecs>
<reqDate>01/01/2021</reqDate>
</RequestInfoField>
<identifierKey>45638</identifierKey>
</FieldDetails>
</Field>
</transfer>
</MyRequest>
Using the following SQL query to retrieve the XML node value of identifierKey, but the query is always returning an empty string :
select
T.RequestXML.query('MyRequest/transfer/Field/FieldDetails/identifierKey') As identifierKey, *
from UserRequest T
You haven't declared your (default) namespace in your SQL:
WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/2004/07/')
SELECT UR.RequestXML.query('MyRequest/transfer/Field/FieldDetails/identifierKey') As identifierKey,
*
FROM dbo.UserRequest UR;
If you, however, explicitly want the value of identifierKey use value, not query.
WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/2004/07/')
SELECT UR.RequestXML.value('(MyRequest/transfer/Field/FieldDetails/identifierKey)[1]','int') AS identifierKey
*
FROM dbo.UserRequest UR;
db<>fiddle
Like this:
declare #doc xml = '<MyRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/">
<transfer>
<Field>
<fieldId>12323</fieldId>
<FieldDetails>
<RequestInfoField>
<requestDecs>Test</requestDecs>
<reqDate>01/01/2021</reqDate>
</RequestInfoField>
<identifierKey>45638</identifierKey>
</FieldDetails>
</Field>
</transfer>
</MyRequest>';
WITH XMLNAMESPACES(DEFAULT 'http://schemas.datacontract.org/2004/07/')
SELECT T.RequestXML.value('(/MyRequest/transfer/Field/FieldDetails/identifierKey)[1]','int') As identifierKey, *
FROM (values(#doc)) T(RequestXML);

SQL query for XML data

I have a SQL Server database table with a column called XML that contains XML data which is structured like this:
<Item xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://test/data">
<Roots>
<Root>
<Name>Field Name</Name>
<Value>Field Value</Value>
</Root>
<Root>
<Name>Field Name</Name>
<Value>Field Value</Value>
</Root>
</Roots>
I want to use T-SQL to get the Value where Name = Total. I have tried the following but it isn't returning any data:
SELECT [XML]
FROM [BusinessAccount]
WHERE [XML].value('(/Root/Name)[13]', 'VARCHAR(MAX)') LIKE '%Total%'
If anyone could tell me where I've gone wrong?
You are missing the required WITH XMLNAMESPACES for your XML and the path is incorrect.
If you want to bring back rows where the 13th element consists of the text Total you can use the below.
WITH XMLNAMESPACES (DEFAULT 'http://test/data')
SELECT [XML]
FROM [BusinessAccount]
WHERE 1 = [XML].exist('(/Item/Roots/Root/Name)[13][text() = "Total"]')
Otherwise you can add the WITH XMLNAMESPACES to your original query and fix the path there too.
You need to specify namespaces. You can then match <Name> and <Value> pairs and extract the contents of <Value> like so:
SELECT NameNode.value('declare namespace x="http://test/data"; (../x:Value)[1]', 'varchar(100)')
FROM [BusinessAccount]
CROSS APPLY [XML].nodes('declare namespace x="http://test/data"; //x:Root/x:Name') AS n(NameNode)
WHERE NameNode.value('.', 'varchar(100)') = 'Total'
Demo on db<>fiddle

SQL query to get most recent date from XML document

I am doing a SQL query against a column with an XML document located.
The XML document looks like the following.
<root>
<date>2016-10-12</date>
<date>2016-12-01</date>
<date>2016-11-13</date>
</root>
As you can see the dates are out of order.
I am looking for a SQL query that will get the most recent date from the XML document (in this case: 2016-12-01).
One way is to read all data and find the maximum externally (external ORDER BY with TOP 1, like in Prdp's answer, or MAX(), eventually with GROUP BY).
Another way is a FLWOR-XQuery:
DECLARE #xml XML=
'<root>
<date>2016-10-12</date>
<date>2016-12-01</date>
<date>2016-11-13</date>
</root>';
SELECT #xml.value('max(for $d in /root/date return xs:date($d))','date')
This means:
Take each value in /root/date, return it as date and find the highest!
Both approaches will need to read the whole list, but it should be a bit faster only to look for the maximum value, rather than return a full list and do some external sorting, picking again...
Try this
DECLARE #xml XML
SET #xml = '<root>
<date>2016-10-12</date>
<date>2016-12-01</date>
<date>2016-11-13</date>
</root>'
SELECT Top 1 x.col.value('.', 'date') AS dates
FROM #xml.nodes('/root/date') x(col)
ORDER BY dates DESC

Flattening xml data in sql

I'm trying to flatten XML data in a SQL query but I always seem to get nulls.
I tried the cross/outer apply method described here.
The column with XML data is called Data.
I'm guessing that the xml data with these links need to be somehow also added?
Could you please help to get a proper SQL query?
Query I tried:
SELECT
v.name
,pref.value('(LocalId/text())[1]', 'nvarchar(10)') as localid
FROM [database].[requests] v
outer apply v.Data.nodes('/DataForm') x(pref)
GO
example of xml data in that column:
<Dataform xmlns="http://somelongasslink.org/hasalsosomestuffhere" xmlns:i="http://somexlmschemalink/">
<DeleteDate xmlns="http://somelongasslink.org/hasalsosomestuffhere" i:nil="true" />
<LocalId xmlns="http://somelongasslink.org/hasalsosomestuffhere">5325325</LocalId>
...
You can use this code to get the result you're looking for:
;WITH XMLNAMESPACES(DEFAULT 'http://somelongasslink.org/hasalsosomestuffhere')
SELECT
rq.Name,
LocalID = TC.value('(LocalId)[1]', 'nvarchar(10)')
FROM
[database].[requests] rq
CROSS APPLY
rq.Data.nodes('/Dataform') AS TX(TC)
GO
There were two problems with your code:
you're not respecting / including the XML namespace that's defined on the XML document
<Dataform xmlns="http://somelongasslink.org/hasalsosomestuffhere"
*******************************************************
you didn't pay attention to the case-sensitivity of XML in your call to .nodes() - you need to use .nodes('/Dataform') (not /DataForm - the F is not capitalized in your XML)