SQL to XML transfer of data - sql

Ok have been trying to learn SQL to XML the last few days and this is what I have been able to teach my self thus far.
`SELECT distinct StudentItem.foldername AS "foldername", StudentItem.status, StudentItem.vhrid, StudentItem.firstname, StudentItem.middleinitial, StudentItem.lastname,
dbo.getEnumDescript(StudentType, 'StudentType') AS title,
StudentItem.email,
dbo.getEnumDescript(OfficeLocation, 'OfficeLocation') AS Office,
practices.id as 'StudentItem/practices/practice/id',
practices.name as 'StudentItem/practices/practice/name',
schoolItem.Name as 'StudentItem/bio/schools/schoolItem/schoolname',
schoolItem.schoolYear as 'lawyerItem/bio/schools/schoolItem/schoolyear'
FROM [dbo].[Student] as lawyerItem
LEFT JOIN [dbo].[StudentGroups] as aprac on StudentItem.vhrid = aprac.vhrid
INNER JOIN [dbo].[PracticeGroups] as practices on aprac.PracticeGroupID = practices.ID
LEFT JOIN [dbo].[StudentEducation] as schoolItem on StudentItem.vhrid = schoolItem.vhrid
where StudentItem.vhrid='50330'
FOR XML path, ROOT ('StudentItem'), ELEMENTS;`
What I get is this
`<StudentItems>
<row>
<foldername>susan.wissink</foldername>
<status>1</status>
<vhrid>50330</vhrid>
<firstname>Susan</firstname>
<middleinitial>M.</middleinitial>
<lastname>Wissink</lastname>
<title>Student leader</title>
<email>swissink#blank.com</email>
<Office>Phoenix</Office>
<StudentItem>
<practices>
<practice>
<id>681</id>
<name>Real Estate Finance and Lending</name>
</practice>
</practices>
<bio>
<schools>
<schoolItem>
<schoolname><i>Best in America®</i>, ASU</schoolname>
<schoolyear>2016</schoolyear>
</schoolItem>
</schools>
</bio>
</StudentItem>
</row>
<row>
<foldername>susan.wissink</foldername>
<status>1</status>
<vhrid>50330</vhrid>
<firstname>Susan</firstname>
<middleinitial>M.</middleinitial>
<lastname>Wissink</lastname>
<title>Student leader</title>
<email>swissink#blank.com</email>
<Office>Phoenix</Office>
<StudentItem>
<practices>
<practice>
<id>681</id>
<name>Real Estate Finance and Lending</name>
</practice>
</practices>
<bio>
<schools>
<schoolItem>
<schoolname><i>Best in America®</i>, UOP</schoolname>
<schoolyear>2011-2015</schoolyear>
</schoolItem>
</schools>
</bio>
</StudentItem>
</row>`
But I'm trying to get the all the practices and schools to show up as one entry for the guy that. More or less I'm trying to get it to look like below.
`<StudentItems>
<row>
<foldername>susan.wissink</foldername>
<status>1</status>
<vhrid>50330</vhrid>
<firstname>Susan</firstname>
<middleinitial>M.</middleinitial>
<lastname>Wissink</lastname>
<title>Student leader</title>
<email>swissink#blank.com</email>
<Office>Phoenix</Office>
<StudentItem>
<practices>
<practice>
<id>681</id>
<name>Real Estate Finance and Lending</name>
<id>683</id>
<name>Business and Finance</name>
</practice>
</practices>
<bio>
<schools>
<schoolItem>
<schoolname><i>Best in America®</i>, UOP</schoolname>
<schoolyear>2011-2015</schoolyear>
<schoolname><i>Best in America®</i>, ASU</schoolname>
<schoolyear>2016</schoolyear>
</schoolItem>
</schools>
</bio>
</StudentItem>
</row>`
Any help would be welcome. Thank You.

Without sample data, it's difficult to write code and test for. But generally what you need to do is to create sub-queries to create your practice and schoolItem XML nodes. Something like this:
SELECT distinct StudentItem.foldername AS "foldername",
StudentItem.status,
StudentItem.vhrid,
StudentItem.firstname,
StudentItem.middleinitial,
StudentItem.lastname,
dbo.getEnumDescript(StudentType, 'StudentType') AS title,
StudentItem.email,
dbo.getEnumDescript(OfficeLocation, 'OfficeLocation') AS Office,
(
select practices.id, practices.name
from [dbo].[StudentGroups] as aprac
INNER JOIN [dbo].[PracticeGroups] as practices
on aprac.PracticeGroupID = practices.ID
where StudentItem.vhrid = aprac.vhrid
FOR XML path(''), type
) 'StudentItem/practices/practice',
(
select Name schoolname, schoolYear
from [dbo].[StudentEducation] schoolItem
where StudentItem.vhrid = schoolItem.vhrid
FOR XML path(''), type
) 'StudentItem/bio/schools/schoolItem'
FROM [dbo].[Student] as StudentItem
where StudentItem.vhrid='50330'
FOR XML path, ROOT ('StudentItem');

Related

How can I output XML with different queries

I am struggling at outputting XML the correct way. I'm trying to generate XML document with SQL Server query, which gives my the following:
CODE USED:
SELECT Plate, tbl_veiculos.ID, Brand, Model, Origin, Color
FROM tbl_veiculos, tbl_veiculo_spec
WHERE tbl_veiculos.ID = tbl_veiculo_spec.ID AND tbl_veiculos.ID = 1
FOR XML PATH ('Vehicle'), TYPE, ROOT('VehicleList')
RESULT:
<VehicleList>
<Vehicle>
<Plate>34-23-nd</Plate>
<ID>1</ID>
<Brand>Mercedes-Benz</Brand>
<Model>A140</Model>
<Origin>Germany</Origin>
<Color>Red</Color>
</Vehicle>
</VehicleList>
Which is to a certain way what I need. The problem comes when I try to merge it with other query output. I know this doesn't explain well so I'll show you an harcoded version of what I want.
<VehicleList>
<Vehicle>
<Plate>34-23-nd</Plate>
<ID>1</ID>
<Brand>Mercedes-Benz</Brand>
<Model>A140</Model>
<SellerInfo>
<Name>Someone Special</Name>
<Street>Oxfod Court 1231</Street>
</SellerInfo>
<Origin>Germany</Origin>
<Color>Red</Color>
</Vehicle>
</VehicleList>
<SellerInfo> comes from other table.
You can use subquery as below:
SELECT Plate, tbl_veiculos.ID, Brand, Model,
(select Name, Street from sellerInfo where id = t1.id --use id to join sellerInfo table
for xml Path(''), type) as SellerInfo,
Origin, Color,
FROM tbl_veiculos t1 inner join tbl_veiculo_spec ts
on tbl_veiculos.ID = tbl_veiculo_spec.ID AND tbl_veiculos.ID = 1
FOR XML PATH ('Vehicle'), TYPE, ROOT('VehicleList')

Using TSQL and For XML Path to generate XML output

I have 3 temp tables all populated by 3 independent queries and are associated to each other with a 1 to 1 relationship, these tables are DemographicRecord, GPRegistrationDetails, MaternityBookingDetails. The columns are different between all 3 but each share the PatientID key. My question is using XML Path how can I output XML from the 3 related datasets following the format below.
<MAT001MothersDemographics>
<LocalPatientIdMother>BLANKED</LocalPatientIdMother>
<OrgCodeLocalPatientIdMother>BLANKED</OrgCodeLocalPatientIdMother>
<OrgCodeRes>BLANKED</OrgCodeRes>
<NHSNumberMother>BLANKED</NHSNumberMother>
<NHSNumberStatusMother>BLANKED</NHSNumberStatusMother>
<PersonBirthDateMother>BLANKED</PersonBirthDateMother>
<Postcode>BLANKED</Postcode>
<EthnicCategoryMother>BLANKED</EthnicCategoryMother>
<PersonDeathDateTimeMother>BLANKED</PersonDeathDateTimeMother>
<MAT003GPPracticeRegistration>
<LocalPatientIdMother>BLANKED</LocalPatientIdMother>
<OrgCodeGMPMother>BLANKED</OrgCodeGMPMother>
<StartDateGMPRegistration>BLANKED</StartDateGMPRegistration>
<EndDateGMPRegistration>BLANKED</EndDateGMPRegistration>
<OrgCodeCommissioner>BLANKED</OrgCodeCommissioner>
</MAT003GPPracticeRegistration>
<MAT101BookingAppointmentDetails>
<AntenatalAppDate>BLANKED</AntenatalAppDate>
<LocalPatientIdMother>BLANKED</LocalPatientIdMother>
<EDDAgreed>BLANKED</EDDAgreed>
<EDDMethodAgreed>BLANKED</EDDMethodAgreed>
<PregnancyFirstContactDate>BLANKED</PregnancyFirstContactDate>
<PregnancyFirstContactCareProfessionalType>BLANKED</PregnancyFirstContactCareProfessionalType>
<LastMenstrualPeriodDate>BLANKED</LastMenstrualPeriodDate>
<PhysicalDisabilityStatusIndMother>BLANKED</PhysicalDisabilityStatusIndMother>
<FirstLanguageEnglishIndMother>BLANKED</FirstLanguageEnglishIndMother>
<EmploymentStatusMother>BLANKED</EmploymentStatusMother>
<SupportStatusMother>BLANKED</SupportStatusMother>
<EmploymentStatusPartner>BLANKED</EmploymentStatusPartner>
<PreviousCaesareanSections>BLANKED</PreviousCaesareanSections>
<PreviousLiveBirths>BLANKED</PreviousLiveBirths>
<PreviousStillBirths>BLANKED</PreviousStillBirths>
<PreviousLossesLessThan24Weeks>BLANKED</PreviousLossesLessThan24Weeks>
<SubstanceUseStatus>BLANKED</SubstanceUseStatus>
<SmokingStatus>BLANKED</SmokingStatus>
<CigarettesPerDay>BLANKED</CigarettesPerDay>
<AlcoholUnitsPerWeek>BLANKED</AlcoholUnitsPerWeek>
<FolicAcidSupplement>BLANKED</FolicAcidSupplement>
<MHPredictionDetectionIndMother>BLANKED</MHPredictionDetectionIndMother>
<PersonWeight>BLANKED</PersonWeight>
<PersonHeight>BLANKED</PersonHeight>
<ComplexSocialFactorsInd>BLANKED</ComplexSocialFactorsInd>
</MAT101BookingAppointmentDetails>
</MAT001MothersDemographics>
So far I have tried:
SELECT
(SELECT * FROM #temp2
JOIN #temp ON #temp2.LocalPatientIdMother = #temp.LocalPatientIdMother
JOIN #temp3 ON #temp2.LocalPatientIdMother = #temp3.LocalPatientIdMother
FOR XML PATH('MAT001'), TYPE) AS 'MAT001MothersDemographics'
FOR XML PATH(''), ROOT('root')
But this is not the correct shape, can someone advise how I can use TSQL and FOR XML PATH effectively so I can generate the above output? I am currently getting the demographics repeated for every record before the other data is displayed?
<MAT001MothersDemographics>
<MAT001>
<LocalPatientIdMother>BLANKED</LocalPatientIdMother>
<OrgCodeLocalPatientIdMother>BLANKED</OrgCodeLocalPatientIdMother>
<OrgCodeRes>BLANKED</OrgCodeRes>
<NHSNumberMother>BLANKED</NHSNumberMother>
<NHSNumberStatusMother>BLANKED</NHSNumberStatusMother>
<PersonBirthDateMother>BLANKED</PersonBirthDateMother>
<Postcode>BLANKED</Postcode>
<EthnicCategoryMother>BLANKED</EthnicCategoryMother>
<PersonDeathDateTimeMother>BLANKED</PersonDeathDateTimeMother>
</MAT001>
</MAT001MothersDemographics>
<MAT001MothersDemographics>
<MAT001>
<LocalPatientIdMother>BLANKED</LocalPatientIdMother>
<OrgCodeLocalPatientIdMother>BLANKED</OrgCodeLocalPatientIdMother>
<OrgCodeRes>BLANKED</OrgCodeRes>
<NHSNumberMother>BLANKED</NHSNumberMother>
<NHSNumberStatusMother>BLANKED</NHSNumberStatusMother>
<PersonBirthDateMother>BLANKED</PersonBirthDateMother>
<Postcode>BLANKED</Postcode>
<EthnicCategoryMother>BLANKED</EthnicCategoryMother>
<PersonDeathDateTimeMother>BLANKED</PersonDeathDateTimeMother>
</MAT001>
</MAT001MothersDemographics>
Thanks very much
I must admit, that your question is quite unclear... You post a lot not needed details (e.g. big XMLs), but you do not provide the necessary information like table's structures and sample data. For the future please read How to ask a good SQL question and How to create a MCVE
But - my magic crystall ball is back from cleaning! - I try a quick shot:
SELECT t.*
,(
SELECT *
FROM #temp2 AS t2
WHERE t.LocalPatientIdMother=t2.LocalPatientIdMother
FOR XML PATH('MAT003GPPracticeRegistration'),TYPE
) AS [*]
,(
SELECT *
FROM #temp3 AS t3
WHERE t.LocalPatientIdMother=t3.LocalPatientIdMother
FOR XML PATH('MAT101BookingAppointmentDetail'),TYPE
) AS [*]
FROM #temp AS t
FOR XML PATH('MAT001MothersDemographics');
This will return all columns of #temp1 and will nest the related rows of #temp2 and #temp3. This is based on the assumption, that you have one record for the given ID in each table only...

Get XML node values using SQL

I'm using SQL Server 2014 and I need help with constructing a query that will give me all of the values for a particular XML node. I have a table that has information stored in it in xml. The xml data is like below:
<category>
<text>Laser Printers</text>
<title id="1">
<text>HP OfficeJet Pro 8610</text>
</text>
<title id="2">
<text>HP OfficeJet Pro 8700</text>
</text>
<title id="3">
<text>Canon PIXMA MX 922</text>
</text>
</category>
I'm only able to get the value from the first node for each row in the table using this query.
SELECT it.contents.value('(category/title/text)[1]', 'NVARCHAR(255)') as Printer
FROM inventory i
INNER JOIN store_products p ON i.inventoryId = p.inventoryId
INNER JOIN items it ON p.itemId = it.itemId
So my result is:
Printer
HP OfficeJet Pro 8610
What I need is the following:
Printer
HP OfficeJet Pro 8610, HP OfficeJet Pro 8700, Canon PIXMA MX 922
Is this even possible?
You need to use CROSS APPLY and the .nodes() XQuery function - something like this:
SELECT
XC.value('(text)[1]', 'varchar(100)') AS Printer
FROM
inventory i
INNER JOIN
store_products p ON i.inventoryId = p.inventoryId
INNER JOIN
items it ON p.itemId = it.itemId
CROSS APPLY
it.contents.nodes('/category/title') AS XT(XC)

Using SQL FOR XML PATH, how can I achieve the following formatted XML output?

The scope of this project is much larger than this one question. I've been tasked with a project and I'll not bore you with the intimate details. Ultimately what I'm needing to do is get the data out of the database and into XML so I can convert to JSON and create a simple web app that will allow me to parse and format the data in way that will meet the customer's needs.
I'm sure there's a better way to do this, but this is the path I've settled on..
I have about 46,000 records dumped into a Temp Table. To Give you an idea of how this data is structured running the following query:
SELECT
TransactionID,
OwnerID,
Date,
TransactionType,
ChargeCode,
Description,
DebitAmount
FROM #OwnerHistoryTemp
WHERE OwnerID = '11111111'
Returns this:
TransactionID OwnerID Date TransactionType ChargeCode Description DebitAmount
28727 11111111 2014-12-01 E A1 APPLY CHARGES 210.00
28728 11111111 2014-12-03 C A1 DB11111111 210.00
28729 11111111 2015-01-01 E A1 APPLY CHARGES 183.37
What I'm looking to do here is use the SQL FOR XML PATH (open to any other suggestions) to output the data like so:
<OwnerHistory>
<OwnerID OwnerID="11111111">
<Transactions>
<TransactionID ID="28727">
<Date>2014-12-01</Date>
<TransactionType>E</TransactionType>
<ChargeCode>A1</ChargeCode>
<Description>APPLY CHARGES</Description>
<DebitAmount>210.00</DebitAmount>
</TransactionID>
<TransactionID ID="28728">
<Date>2014-12-03</Date>
<TransactionType>C</TransactionType>
<ChargeCode>A1</ChargeCode>
<Description>DB11111111</Description>
<DebitAmount>210.00</DebitAmount>
</TransactionID>
<TransactionID ID="28729">
<Date>2015-1-01</Date>
<TransactionType>E</TransactionType>
<ChargeCode>A1</ChargeCode>
<Description>APPLY CHARGES</Description>
<DebitAmount>183.37</DebitAmount>
</TransactionID>
</Transactions>
</OwnerID>
</OwnerHistory>
The Query I have, gets me close, but not QUITE there. Because the same OwnerID appears multiple times (once for each TransactionID), running the following query:
SELECT
OwnerID AS "#OwnerID",
TransactionID AS "Transaction/#RecordID",
Date AS "Transaction/Date",
TransactionType AS "Transaction/TransactionType",
ChargeCode AS "Transaction/ChargeCode",
Description AS "Transaction/Description",
DebitAmount AS "Transaction/DebitAmount"
FROM #OwnerHistoryTemp
WHERE OwnerID = '11111111'
GROUP BY OwnerID, RecordID, Date, ChargeCode, Description, DebitAmount
order by OwnerID
FOR XML PATH ('OwnerID'), ROOT('OwnerHistory')
Returns the folowing:
<OwnerHistory>
<OwnerID OwnerID="11111111">
<Transaction RecordID="28727">
<Date>2014-12-01</Date>
<TransactionType>E</TransactionType>
<ChargeCode>A1</ChargeCode>
<Description>APPLY CHARGES</Description>
<DebitAmount>210.0000</DebitAmount>
</Transaction>
</OwnerID>
<OwnerID OwnerID="11111111">
<Transaction RecordID="28728">
<Date>2014-12-03</Date>
<TransactionType>C</TransactionType>
<ChargeCode>A1</ChargeCode>
<Description>DB11111111</Description>
<DebitAmount>210.0000</DebitAmount>
</Transaction>
</OwnerID>
<OwnerID OwnerID="11111111">
<Transaction RecordID="28729">
<Date>2015-01-01</Date>
<TransactionType>E</TransactionType>
<ChargeCode>A1</ChargeCode>
<Description>APPLY CHARGES</Description>
<DebitAmount>183.3700</DebitAmount>
</Transaction>
</OwnerID>
</OwnerHistory>
Any thoughts on how to only pull the OwnerID one time as the Parent and group all transactions underneath it?
Might be something simple I'm just not understanding, or it might be impossible. Feel free to publicly cane me if the former is the case...
Ready for your caning?
Nest your queries to get nested XML, something like this:
SELECT TOP 1
OwnerID AS "#ID",
(SELECT
TransactionID AS "Transaction/#ID",
[Date] AS "Transaction/Date",
TransactionType AS "Transaction/Type",
ChargeCode AS "Transaction/ChargeCode",
[Description] AS "Transaction/Description",
DebitAmount AS "Transaction/DebitAmount"
FROM OwnerHistory
WHERE OwnerID = [Owner].OwnerID
FOR XML PATH(''), TYPE) Transactions
FROM OwnerHistory [Owner]
WHERE OwnerID = '11111111'
FOR XML PATH('Owner'), ROOT('OwnerHistory'), TYPE
Resulting XML:
<OwnerHistory>
<Owner ID="11111111">
<Transactions>
<Transaction ID="28727">
<Date>2015-03-26</Date>
<Type>E</Type>
<ChargeCode>A1</ChargeCode>
<Description>APPLY CHARGES</Description>
<DebitAmount>210.0000</DebitAmount>
</Transaction>
<Transaction ID="28728">
<Date>2015-03-26</Date>
<Type>C</Type>
<ChargeCode>A1</ChargeCode>
<Description>DB11111111</Description>
<DebitAmount>210.0000</DebitAmount>
</Transaction>
<Transaction ID="28729">
<Date>2015-03-26</Date>
<Type>E</Type>
<ChargeCode>A1</ChargeCode>
<Description>APPLY CHARGES</Description>
<DebitAmount>183.3700</DebitAmount>
</Transaction>
</Transactions>
</Owner>
</OwnerHistory>
Note that the TOP 1 is only included to avoid repeating the entire set of transactions for each row containing the OwnerID. This could be handled in a number of ways; normally this sort of nesting would be the result of a join on two normalized tables so that only one instance of Owner would occur.
MSDN has some good examples to demonstrate this technique.

How to get xml from many records?

So I have the below that will allow me to get xml from one record in the Products table.
However, I need to to be able to get the XML from ALL records in the Products table, along with its ProductId.
I'm confused on how to start this.
DECLARE #MyXML XML
SET #MyXML =
(SELECT ProductsXML
FROM Products
WHERE ProductId= 1)
SELECT
a.b.value('#upccode','int') as UPC,
a.b.value('#dateadded','date') as DateAdded
FROM
#MyXML.nodes('xml/Product/UPC')a(b);
I'm using SQL Server 2008.
Test Data:
ProductId: 1
ProductsXML:
<xml>
<Product>
<UPC upccode="1237" dateadded="10/9/2012"/>
<UPC upccode="1236" dateadded="10/8/2012"/>
<UPC upccode="1235" dateadded="10/7/2012"/>
<UPC upccode="1234" dateadded="10/6/2012"/>
</Product>
</xml>
ProductId: 2
ProductsXML:
<xml>
<Product>
<UPC upccode="9876" dateadded="9/9/2012"/>
<UPC upccode="9877" dateadded="9/8/2012"/>
<UPC upccode="0998" dateadded="9/7/2012"/>
<UPC upccode="7877" dateadded="9/6/2012"/>
</Product>
</xml>
The Result I'm looking for is something like this:
ProductId UPC DateAdded
--------- --- ---------
1 1237 10/9/2012
1 1236 10/8/2012
....
2 9876 9/9/2012
2 9877 9/8/2012
Right now I can get the above but ONLY by specifying one PoductId at a time. I want to be able to run all of the `Products' without specifying each entry.
I guess you are looking for something like this.
SELECT ProductId,
a.b.value('#upccode','int') as UPC,
a.b.value('#dateadded','date') as DateAdded
FROM Products
CROSS APPLY ProductsXML.nodes('xml/Product/UPC')a(b);
There is no need to have a XML variable in there. Query the Products table directly and use CROSS APPLY against ProductsXML field to shred your XML.
hi u can try using Linq to xml to create an entity from the xml, see the sample code below
XDocument somedoc = XDocument.Load("your xml path");
var somelist = from somevariable in somedoc.Descendants("Product")
select new Product {
UPC = somevariable.Attribute("upccode").value
DateAdded = somevariable.Attribute("dateadded").value
}
so now somelist is a collection thru which u can iterate and add to List<Product>, create product b4 u start tryinh this