sql select data from XML param - sql

whats the SQL for selecting the values from this XML chunk like done in the sample below?
<RWFCriteria reportType="OPRAProject">
<item id="88" name="" value="" type="Project" />
<item id="112" name="" value="12" type="Milestone" />
<item id="43" name="" value="11" type="Milestone" />
</RWFCriteria>
i want to select out similar to this but with the above XML data
DECLARE #Param XML
SET #Param = '<data>
<release id="1"><milestone id="1" /><milestone id="2" /></release>
<release id="3"><milestone id="1" /><milestone id="27"/></release>
</data>'
SELECT c.value('../#id', 'INT') AS ReleaseId, c.value('#id', 'INT') AS MilestoneId
FROM #Param.nodes('/data/release/milestone') AS T(c)
I want only the data in the nodes where type="Milestone"

Something like this:
DECLARE #Param XML
SET #Param = '<RWFCriteria reportType="OPRAProject">
<item id="88" name="" value="" type="Project" />
<item id="112" name="" value="12" type="Milestone" />
<item id="43" name="" value="11" type="Milestone" />
</RWFCriteria>'
SELECT
RWF.item.value('#id', 'INT') AS 'Id',
RWF.item.value('#name', 'VARCHAR(100)') AS 'Name',
RWF.item.value('#value', 'INT') AS 'Value',
RWF.item.value('#type', 'VARCHAR(100)') AS 'Type'
FROM
#Param.nodes('/RWFCriteria/item') AS RWF(item)
WHERE
RWF.item.value('#type', 'VARCHAR(100)') = 'Milestone'
Resulting output:
Id Name Value Type
112 12 Milestone
43 11 Milestone

Related

How to read attributes in a XML file using nodes in SQL

I am trying to read ALL the Items from this XML using nodes but I jus manage to return just very first one, or none with the following examples.
How to read the entire list?
The file can contain hundreds of thousands.
XML file
<data source="1" target="0">
<list item_nb="1">
<co id="1" constitution="20190612101007" item_nb="44046">
<item cm="640001000101" obu="00007E" vc="2" vrn="SOLD" />
<item cm="640001000101" obu="00009D" vc="6" vrn="04D11797" />
<item cm="640001000101" obu="0000A3" vc="2" vrn="FAULTY" />
<item cm="640001000101" obu="00018B" vc="2" vrn="07D54084" />
<item cm="640001000101" obu="0001A6" vc="6" vrn="000422" />
<item cm="640001000101" obu="0001B2" vc="2" vrn="90D24430" />
<item cm="640001000101" obu="0001B3" vc="2" vrn="03LS1592" />
<item cm="640001000101" obu="0001B9" vc="6" vrn="FAULTYJUNE15" />
</co>
</list>
</data>
My Code in SQL (return only the first item)
declare #X xml;
select #X = T.MY_XML
from openrowset(bulk 'C:\XML\IEA.1.20190612101007-WL.XML', single_blob) as T(MY_XML)
select
MY_XML.Item.value('(item/#cm)[1]', 'VARCHAR(20)'),
MY_XML.Item.value('(item/#obu)[1]', 'VARCHAR(50)'),
MY_XML.Item.value('(item/#vc)[1]', 'VARCHAR(50)'),
MY_XML.Item.value('(item/#vrn)[1]', 'VARCHAR(50)')
from #X.nodes('data/list/co') AS MY_XML (Item);
found a way to work!
declare #X xml;
select #X = T.MY_XML
from openrowset(bulk 'C:\XML\IEA.1.20190612101007-WL.XML', single_blob) as T(MY_XML)
select
MY_XML.Item.value('(#cm)[1]', 'VARCHAR(20)'),
MY_XML.Item.value('(#obu)[1]', 'VARCHAR(50)'),
MY_XML.Item.value('(#vc)[1]', 'VARCHAR(50)'),
MY_XML.Item.value('(#vrn)[1]', 'VARCHAR(50)')
from #X.nodes('data/list/co/item') AS MY_XML (Item);

SQL Server : Count of XML Elements By Element Name

I have successfully obtained a count of sub elements using this query.
SELECT
raa.ApplicationXML.value('count(Root/ThirdParty/*)', 'Int') as [Bureau Count]
FROM
Table1 raa
However, I want to group this count by the actual name of the sub element.
My XML looks something like this:
Record 1:
<Root>
<ThirdParty>
<BureauRed />
<BureauGreen />
<BureauBlue />
</ThirdParty>
</Root>
Record 2:
<Root>
<ThirdParty>
<BureauRed />
<BureauPurple />
<BureauBlue />
</ThirdParty>
</Root>
Record 3:
<Root>
<ThirdParty>
<BureauGreen />
<BureauRed />
<BureauPurple />
<BureauOrange />
<BureauBlue />
</ThirdParty>
</Root>
Not only do I need to pull the count of each bureau, but I need to get the name of the bureau (BureauRed, BureauGreen, BureauBlue, etc.) When I try to group by count I get the error:
XML methods are not allowed in a GROUP BY clause.
Using this query:
SELECT
raa.ApplicationXML.value('count(Root/ThirdParty/*)', 'Int') as [Bureau Count]
FROM
Table1 raa
GROUP BY
raa.ApplicationXML.value('count(Root/ThirdParty/*)', 'Int')
How do I get the count and the name of the bureau?
I'm looking for this result:
Bureau Count
============ =====
BureauRed 3
BureauGreen 2
BureauBlue 3
BureauPurple 2
BureauOrange 1
You can group after recieving data via XQuery:
DECLARE #xml1 xml =
'<Root>
<ThirdParty>
<BureauRed />
<BureauGreen />
<BureauBlue />
</ThirdParty>
</Root>';
DECLARE #xml2 xml =
'<Root>
<ThirdParty>
<BureauRed />
<BureauPurple />
<BureauBlue />
</ThirdParty>
</Root>';
DECLARE #xml3 xml =
'<Root>
<ThirdParty>
<BureauGreen />
<BureauRed />
<BureauPurple />
<BureauOrange />
<BureauBlue />
</ThirdParty>
</Root>';
DECLARE #temp TABLE (XmlData xml);
INSERT #temp VALUES (#xml1), (#xml2), (#xml3);
WITH cte AS
(
SELECT n.value('local-name(.)', 'varchar(50)') nodeName
FROM #temp t
CROSS APPLY t.XmlData.nodes('/Root/ThirdParty/*') x(n)
)
SELECT nodeName, count(*) cnt
FROM cte
GROUP BY nodeName;
Output:
nodeName cnt
-------------------------------------------------- -----------
BureauBlue 3
BureauGreen 2
BureauOrange 1
BureauPurple 2
BureauRed 3
You need to extract the elements that are children of Root/ThirdParty first and use that derived table to do the counting.
DECLARE #tv TABLE(x XML);
INSERT INTO #tv(x)VALUES(
N'<Root>
<ThirdParty>
<BureauRed />
<BureauGreen />
<BureauBlue />
</ThirdParty>
</Root>'),(
N'<Root>
<ThirdParty>
<BureauRed />
<BureauPurple />
<BureauBlue />
</ThirdParty>
</Root>'),(
N'<Root>
<ThirdParty>
<BureauGreen />
<BureauRed />
<BureauPurple />
<BureauOrange />
<BureauBlue />
</ThirdParty>
</Root>');
WITH bureaus AS (
SELECT
bureau=n.v.value('local-name(.)','NVARCHAR(256)')
FROM
#tv
CROSS APPLY x.nodes('/Root/ThirdParty/*') AS n(v)
)
SELECT
bureau,
[count]=COUNT(*)
FROM
bureaus
GROUP BY
bureau
ORDER BY
bureau;

Get XML from different Tables

Good day to you!
I have a question. Can't get how combine 2 tables in 1 result XML.
Here is the sample
DECLARE #t1 table (ID int identity(1,1), SomeField varchar(50))
DECLARE #t2 table (ID int identity(1,1), SomeField varchar(50), AnotherField varchar(50))
INSERT INTO #t1 (SomeField) VALUES ('rec1'),('rec2'),('rec3'),('rec4')
INSERT INTO #t2 (SomeField,AnotherField) VALUES ('s106','here'),('s12','just'),('s13','sample')
SELECT * FROM #t1 AS FirstTable
SELECT * FROM #t2 AS AnotherTable
Wanted result:
<Root>
<FirstTable ID="1" SomeField="rec1" />
<FirstTable ID="2" SomeField="rec2" />
<FirstTable ID="3" SomeField="rec3" />
<FirstTable ID="4" SomeField="rec4" />
<AnotherTable ID="1" SomeField="s106" AnotherField="here" />
<AnotherTable ID="2" SomeField="s12" AnotherField="just" />
<AnotherTable ID="3" SomeField="s13" AnotherField="sample" />
</Root>
dbfiddle here
New remark (edited)
answered by John Cappelletti, but need put all this inside third table.
Here is new code:
DECLARE #t1 table (ID int identity(1,1), tID int, SomeField varchar(50))
DECLARE #t2 table (ID int identity(1,1), tID int, SomeField varchar(50), AnotherField varchar(50))
DECLARE #t3 table (ID int identity(1,1), field1 varchar(50), field2 varchar(50))
INSERT INTO #t1 (tID,SomeField) VALUES (1,'rec1'),(1,'rec2'),(1,'rec3'),(1,'rec4')
INSERT INTO #t2 (tID,SomeField,AnotherField) VALUES (1,'s106','here'),(1,'s12','just'),(1,'s13','sample')
INSERT INTO #t3 (field1,field2) VALUES ('field1 Value','field2 Value')
Wanted result (finally):
<ThirdTable ID="1" field1="field1 Value" field2="field2 Value">
<FirstTable ID="1" tID="1" SomeField="rec1" />
<FirstTable ID="2" tID="1" SomeField="rec2" />
<FirstTable ID="3" tID="1" SomeField="rec3" />
<FirstTable ID="4" tID="1" SomeField="rec4" />
<AnotherTable ID="1" tID="1" SomeField="s106" AnotherField="here" />
<AnotherTable ID="2" tID="1" SomeField="s12" AnotherField="just" />
<AnotherTable ID="3" tID="1" SomeField="s13" AnotherField="sample" />
</ThirdTable>
Select [root] = cast((Select * From #t1 for xml raw('FirstTable'))
+(Select * From #t2 for xml raw('AnotherTable'))
as xml)
For XML Path(''),Type
Returns
<root>
<FirstTable ID="1" SomeField="rec1" />
<FirstTable ID="2" SomeField="rec2" />
<FirstTable ID="3" SomeField="rec3" />
<FirstTable ID="4" SomeField="rec4" />
<AnotherTable ID="1" SomeField="s106" AnotherField="here" />
<AnotherTable ID="2" SomeField="s12" AnotherField="just" />
<AnotherTable ID="3" SomeField="s13" AnotherField="sample" />
</root>
Added for the Extended Question
Select *
,(select cast(
isnull((Select * From #t1 for xml raw('FirstTable')),'')
+isnull((Select * From #t2 for xml raw('AnotherTable')),'')
as xml)
)
From #t3 for xml raw('ThirdTable')
Returns
<ThirdTable ID="1" field1="field1 Value" field2="field2 Value">
<FirstTable ID="1" tID="1" SomeField="rec1" />
<FirstTable ID="2" tID="1" SomeField="rec2" />
<FirstTable ID="3" tID="1" SomeField="rec3" />
<FirstTable ID="4" tID="1" SomeField="rec4" />
<AnotherTable ID="1" tID="1" SomeField="s106" AnotherField="here" />
<AnotherTable ID="2" tID="1" SomeField="s12" AnotherField="just" />
<AnotherTable ID="3" tID="1" SomeField="s13" AnotherField="sample" />
</ThirdTable>

How to get value from XML in stored procedure?

Can you all help me for this problem?
I want to get value from following XML in sql stored procedure. I don't get vlaue if 'xsi:type="ActiveDirectoryItem"' is in tag 'anyType', and 'ActiveDirectoryItems' tag is also with URLs. How can i do to get only values?
<?xml version="1.0" encoding="utf-8" ?>
<ActiveDirectoryItems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<Items>
<anyType xsi:type="ActiveDirectoryItem">
<FirstName />
<MiddleInitial />
<LastName />
<DisplayName>Migrate-group</DisplayName>
<UserPrincipalName />
<PostalAddress />
<ResidentialAddress />
<Title />
<HomePhone />
<OfficePhone />
<Mobile />
<Fax />
<Email>Migrate-group#gmail.com</Email>
<Url />
<AccountName>Migrate-group</AccountName>
<DistinguishedName />
<IsAccountActive>false</IsAccountActive>
<ManagedBy />
<Manager />
<CompareType>0</CompareType>
<Description />
<Department />
<Company />
<Type />
</anyType>
</Items>
<GlobalCatalog />
</ActiveDirectoryItems>
The format i want to get is as the following:
DisplayName Email Account Name
Migrate-group Migrate-group#gmail.com Migrate-group
you can use the value keyword
Example:
DECLARE #MyXml XML = '<Root><SomeData>100</SomeData></Root>'
DECLARE #Something INT
SELECT #Something = #MyXml.value('(//Root/SomeData)[1]', 'INT')

T-SQL Dynamic xquery

I am trying to figure out how I can load my table variable with data from XML using dynamic xquery? I am getting a result set of nodes from the query and defining the value type of those nodes. It seems that it is the value definition of the nodes that it is blowing up on.
Here is an example of the script that works, but is not dynamic.
Script:
DECLARE #XML XML = '<root>
<data>
<list id="organization" label="Organization">
<options>
<item value="1" label="Organization1" selected="false" />
<item value="2" label="Organization2" selected="false" />
<item value="3" label="Organization3" selected="false" />
<item value="4" label="Organization4" selected="true" />
<item value="5" label="Organization5" selected="true" />
</options>
</list>
</data>
</root>';
DECLARE #Orgs TABLE (ID INT);
Insert Into #Orgs(ID) Select OrgNameIdNodes.ID.value('#value','int') from #xml.nodes('//*[#id="organization"]//item[#selected="true"]') as OrgNameIdNodes(ID);
Select *
from #orgs
What I would like to be able to do is pass in parameters for both value and the #xml.nodes sections so I would have something like:
Insert Into #Orgs(ID) Select OrgNameIdNodes.ID.value(#Value) from #xml.nodes(#Nodes) as OrgNameIdNodes(ID);
Is this possible?
How about using sp_executesql with dynamic sql. Something like:
DECLARE #XML XML = '<root>
<data>
<list id="organization" label="Organization">
<options>
<item value="1" label="Organization1" selected="false" />
<item value="2" label="Organization2" selected="false" />
<item value="3" label="Organization3" selected="false" />
<item value="4" label="Organization4" selected="true" />
<item value="5" label="Organization5" selected="true" />
</options>
</list>
</data>
</root>';
declare #orgs table(ID int);
declare #nodes nvarchar(4000),
#value nvarchar(4000),
#query nvarchar(4000)
select #value = '''#value'',''int'''
select #nodes = '//*[#id="organization"]//item[#selected="true"]'
select #query = 'Select OrgNameIdNodes.ID.value( ' + #value + ') ' +
'from #xml.nodes(''' + #nodes + ''') as OrgNameIdNodes(ID)'
insert into #Orgs(ID) EXEC sp_executesql #query, N'#xml xml', #xml = #xml
Select *
from #orgs