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)
Related
I am trying to use BizTalk adapter (SQL or WCF-SQL) to create a multilevel hierarchical schema. My query is like this
SELECT
CustomerQueueMessage.customer_queue_ID AS CustomerQueueMsgID,
CustomerMaster.customer_ID AS [CustomerID],
CustomerAddressType.address_type_ID AS [AddressTypeID],
CustomerSalesRep.sales_rep_type_code AS [SalesRepTypeCode]
FROM CustomerQueue AS CustomerQueueMessage
INNER JOIN dbo.MDM_Customer AS CustomerMaster ON (CustomerQueueMessage.customer_queue_ID = CustomerMaster.customer_queue_ID)
INNER JOIN dbo.MDM_CustomerAddressType AS CustomerAddressType ON (CustomerAddressType.customer_queue_ID = CustomerMaster.customer_queue_ID)
INNER JOIN dbo.MDM_CustomerSalesRep AS CustomerSalesRep ON (CustomerSalesRep.customer_queue_ID = CustomerMaster.customer_queue_ID)
FOR XML AUTO, TYPE, ELEMENTS, XMLDATA
When I generate the schema using SQL adapter I get this structure
what I want is
Table CustomerSalesRep is under CustomerAddressType. I want CustomerSalesRep to be at the same level with CustomerAddressType, both immediately under CustomerMaster.
If I remove the FOR XML statement and use WCF-SQL adapter to generate the schema, I get no hierarchy, all the columns are at the same level.
Any ideas? Preferably I would like to do it using WCF-SQL adapter, but also SQL would be OK.
You can use this.
SELECT
CustomerSalesRep.sales_rep_type_code AS "CustomerQueueMessage/CustomerMaster/CustomerSalesRep/SalesRepTypeCode",
CustomerAddressType.address_type_ID AS "CustomerQueueMessage/CustomerMaster/CustomerAddressType/AddressTypeID",
CustomerMaster.customer_ID AS "CustomerQueueMessage/CustomerMaster/CustomerID",
CustomerQueueMessage.customer_queue_ID AS "CustomerQueueMessage/CustomerQueueMsgID"
FROM CustomerQueue AS CustomerQueueMessage
INNER JOIN dbo.MDM_Customer AS CustomerMaster ON (CustomerQueueMessage.customer_queue_ID = CustomerMaster.customer_queue_ID)
INNER JOIN dbo.MDM_CustomerAddressType AS CustomerAddressType ON (CustomerAddressType.customer_queue_ID = CustomerMaster.customer_queue_ID)
INNER JOIN dbo.MDM_CustomerSalesRep AS CustomerSalesRep ON (CustomerSalesRep.customer_queue_ID = CustomerMaster.customer_queue_ID)
FOR XML PATH('SAPcustom'), TYPE, ELEMENTS
It generates an XML like this.
<SAPcustom>
<CustomerQueueMessage>
<CustomerMaster>
<CustomerSalesRep>
<SalesRepTypeCode>1</SalesRepTypeCode>
</CustomerSalesRep>
<CustomerAddressType>
<AddressTypeID>1</AddressTypeID>
</CustomerAddressType>
<CustomerID>1</CustomerID>
</CustomerMaster>
<CustomerQueueMsgID>1</CustomerQueueMsgID>
</CustomerQueueMessage>
</SAPcustom>
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')
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');
I'm stuck with a SQL query (for SQL Server). I'm new to SQL and I'm not making much progress. I've created a test project to test tagging.
I have 3 tables as follows:
Monster:
Name Description EatsPeople
Vampire Pale, afraid of light True
Ghost See-through, annoying False
Wraith Green-ish, ugly, dumb True
TagLookup:
Name ID
Ghost 1
Ghost 2
Wraith 1
Tags:
ID Text Value
1 Green green-skin
2 Screams like a banshee banshee-call
I'm trying to select all monsters that have the tag value 'green-skin'.
Assuming that Monsters.Name, Tags.Value, and the Name-ID combination in TagLookup are all unique:
SELECT m.Name, m.Description, m.EatsPeople
FROM dbo.Monster AS m
INNER JOIN dbo.TagLookup AS tl
ON m.Name = tl.Name
INNER JOIN dbo.Tags AS t
ON t.ID = tl.ID
AND t.Value = 'green-skin';
I have this query:
select top(2)
property_id_ref
,image_file
,property_name
from property_master a
inner join image_master b
on a.property_id=b.property_id_ref
inner join customer_master c
on a.customer_id=c.customer_id
When I execute it, I get the following result:
512 ~/propertyimg/3954493 id_1.jpg Commercial Land
512 ~/propertyimg/3954493.jpg Commercial Land
But I need the output distinct property_id_ref with random image_file from the property_id_ref like this:
512 ~/propertyimg/3954493 id_1.jpg Commercial Land
513 ~/propertyimg/3119918 Id.jpg Residential Plot
For that I made a query like:
select top(2)
max(pm.property_name) as property_name
,max(im.property_id_ref) as property_id_ref
,CONVERT(varchar(5000), max( CONVERT(binary, im.image_file))) as image_file
from property_master pm
inner join image_master im
on pm.property_id=im.property_id_ref
inner join customer_master cm
on pm.customer_id=cm.customer_id
group by im.property_id_ref
So I got the same output as the one I expected. I want to know whether this is the right way to do it, or is there any other better way of doing the same thing?
I am using SQL Server 2005.
If you really only have that query you posted in example, this will work fine:
SELECT TOP (2)
pm.property_id,
pm.property_name,
(SELECT TOP 1 image_file
FROM image_master
WHERE property_id_ref = pm.property_id) AS image_file
FROM
property_master pm
-- This is only needed if it's possible that [image_file] can be NULL and you
-- don't want to get those rows.
WHERE
EXISTS (SELECT * FROM image_master
WHERE property_id_ref = pm.property_id)
I assume your query is more complex than that though, but I can't give you a more specific query unless you post your real query.
The way you do is the right one.
An group by of the ID_Ref and a random member by max.
It's completly OK and I see no reason why to change it.