I have 3 tables
Master {MasterID, Desc},
Detail {MasterID, DetailID, ItemID},
Items {ItemID, ItemDesc})
I want to select Master, Detail (as SubElement in Master), Item (in same element of Detail)
SELECT Master.MasterID, Master.Desc, Detail.DetailID, Detail.ItemID, Items.ItemDesc
FROM Master
LEFT JOIN Detail
LEFT JOIN Items
ON Detail.ItemID = Items.ItemID
ON Master.MasterID = Detail.MasterID
FOR XML AUTO, ELEMENTS
it gives result below:
<Master>
<MasterID>1</MasterID>
<Desc>Master1</Desc>
<Detail>
<DetailID>1</DetailID>
<ItemID>1</ItemID>
<Items><ItemDesc>ItemDesc1</ItemDesc></Items>
</Detail>
</Master>
But my target is
<Master>
<MasterID>1</MasterID>
<Desc>Master1</Desc>
<Detail>
<DetailID>1</DetailID>
<ItemID>1</ItemID>
<ItemDesc>ItemDesc1</ItemDesc>
</Detail>
</Master>'
How can I do that with best practice way?
Make the detail and item description come back from a single query, like so:
SELECT
Master.MasterID,
Master.Desc,
Detail.DetailID,
Detail.ItemID,
Detail.ItemDesc
FROM
Master
LEFT JOIN (
select
d.MasterID,
d.DetailID,
d.ItemID,
i.ItemDesc
from
Detail d
left join items i on
d.itemid = i.itemid
) Detail ON
Master.MasterID = Detail.MasterID
FOR XML AUTO, ELEMENTS
You can use for xml path like this.
select m.MasterID,
m.[Desc],
(select d.DetailID,
d.ItemID,
i.ItemDesc
from Detail as d
inner join Items as i
on d.ItemID = i.ItemID
where d.MasterID = m.MasterID
for xml path('Detail'), type)
from Master as m
for xml path('Master')
Related
SELECT DISTINCT
CD.CASE_NO AS CaseNumber ,
CE.PROCEEDING_ID AS ProceedingId,
PR.AC_STATE_CD AS ForeclosureStatecode,
0 AS STATUS,
GETDATE() AS CreatedDate,
1 AS CreatedBy,
GETDATE() AS ModifiedDate,
1 AS ModifiedBy,
(
select * from TBL_PROPERTY FOR XML PATH('T')
)
from TBL_CASE_DETAIL CD WITH(NOLOCK)
INNER JOIN TBL_AUCTION_DETAIL AD WITH(NOLOCK) ON AD.CASE_DETAIL_ID = CD.CASE_DETAIL_ID
LEFT JOIN TBL_AUCTION_PROPERTY_MAPPING TAPM WITH(NOLOCK) ON TAPM.AUCTION_ID = AD.AUCTION_ID
LEFT JOIN TBL_PROPERTY PR WITH(NOLOCK) ON PR.PROPERTY_ID = TAPM.PROPERTY_ID
LEFT JOIN TBL_AUCTION_PROCEEDING_MAPPING APM WITH(NOLOCK) ON APM.AUCTION_ID = AD.AUCTION_ID
FOR XML PATH('Foreclosure')
Hi Guys, This is my modified code to get a distinct result. but now property part cannot display properly..
This is the result I get it. suppose open another tab for property lets say have 3 property.. so in 1 tab of foreclosure,inside foreclosure have 3 property data, then close foreclose tab..
https://gyazo.com/8a54690c88df3e9bb0dd7ff916c6f86c
Thank You.
If I get this right, the only thing you have to add is ,TYPE. Otherwise your inner SELECT ... FOR XML PATH() is filled i as text with all forbidden characters escaped...
Try:
(
select * from TBL_PROPERTY FOR XML PATH('T'),TYPE
)
I have a Link structure table with ID and parentID.
ID, Parent, name
1,1
2,1
3,2
4,3
5,3
To this table I have a structure_article relation table
in this table I have relation between a Link and a article.
struture_article
structid, articleID
4,1000
4,1001
5,1002
Every article in that table have a supplier.
Now i am trying to create a recursive function that creates the tree
nods if i pick a specific supplier.
Article table
ArticleID, SUPPLIER ID
1000,1
1001,2
1002,2
If I pick articles with supplier 1 then I want the function to show me the tree structure that have articles from that supplier.
I have 20 suppliers and 300 links in the DB now i want only to show articles from the suppliers i pick. I don want any empty nods.
Is this even possible do create with a recursive function in Sql Server version 2008?
I tyied wiht this code the problem is that i get only nods that have articles connected
WITH a
AS (SELECT *
FROM structure
WHERE parent = 125
UNION ALL
SELECT m.*
FROM structure m
JOIN a
ON m.parent = a.internidstructure)
SELECT *
FROM a
WHERE internidstructure IN (SELECT DISTINCT( internidstructure )
FROM dbo.articles
INNER JOIN dbo.structure_article
ON dbo.articles.internidarticle =
dbo.structure_article.internidarticle
WHERE ( dbo.articles.internidsupplier IN (SELECT
internidsupplier
FROM site_sup
WHERE
internidsite = 1) ))
ORDER BY parent,
sortno
Try using a left join instead of an inner join.
I'm not sure to have understood your need but if you want to have a new tree table without nodes not linked to a supplier, this query can work.
WITH A AS
(
SELECT S.ID as ID, S.Parent as Parent, 1 as art_linked
FROM structure S
INNER JOIN dbo.structure_article SA
ON S.ID = SA.structid
INNER JOIN Article AR
ON AR.ArticleID = SA.ArticleID
WHERE AR.SupplierID = 1
UNION ALL
SELECT S.ID, S.Parent, 0
FROM structure S
INNER JOIN A
ON A.parent = S.ID
WHERE S.ID <> S.Parent
)
SELECT A.ID, A.Parent, MAX(A.art_linked)
FROM A
GROUP BY A.ID, A.Parent
I was fiddling with XML AUTO and XML RAW to see how they behave. The test db is AdventureWorks2012.
SELECT TOP 20 Cust.CustomerID AS C1,
Cust.TerritoryID,
OrderHeader.CustomerID AS C2,
OrderHeader.SalesOrderID,
OrderHeader.Status
FROM Sales.Customer Cust
INNER JOIN Sales.SalesOrderHeader OrderHeader
ON Cust.CustomerID = OrderHeader.CustomerID
FOR XML RAW('MyRow'), ELEMENTS
XML RAW's simplicity just puts every element in the same level
<MyRow>
<C1>29825</C1>
<TerritoryID>5</TerritoryID>
<C2>29825</C2>
<SalesOrderID>43659</SalesOrderID>
<Status>5</Status>
While for XML AUTO
SELECT TOP 20 Cust.CustomerID,
Cust.TerritoryID,
OrderHeader.CustomerID,
OrderHeader.SalesOrderID,
OrderHeader.Status
FROM Sales.Customer Cust
INNER JOIN Sales.SalesOrderHeader OrderHeader
ON Cust.CustomerID = OrderHeader.CustomerID
FOR XML AUTO, ELEMENTS
I have
<Cust>
<CustomerID>29825</CustomerID>
<TerritoryID>5</TerritoryID>
<OrderHeader>
<CustomerID>29825</CustomerID>
<SalesOrderID>43659</SalesOrderID>
<Status>5</Status>
</OrderHeader>
</Cust>
XML AUTO decides to group all under Cust tag. How does it come to this conclusion that Cust somehow encloses and "at a higher level" than OrderHeader. Why does it decide to group all OrderHeader's columns under OrderHeader tag and not the same for Cust ? Before executing I thought that it would be
<Cust>
<CustomerID>29825</CustomerID>
<TerritoryID>5</TerritoryID>
</Cust>
<OrderHeader>
<CustomerID>29825</CustomerID>
<SalesOrderID>43659</SalesOrderID>
<Status>5</Status>
</OrderHeader>
Update
It's a hunch but I start to think SQL Server will take the table of the column first mentioned to be the outer tag,
For example,
SELECT TOP 20 OrderHeader.CustomerID,,
Cust.CustomerID,
Cust.TerritoryID,
OrderHeader.SalesOrderID,
OrderHeader.Status
Even when I mix the column order, it will still group columns of OrderHeader together, and Cust is a subgroup
<OrderHeader>
<CustomerID>29825</CustomerID>
<SalesOrderID>43659</SalesOrderID>
<Status>5</Status>
<Cust>
<CustomerID>29825</CustomerID>
<TerritoryID>5</TerritoryID>
</Cust>
</OrderHeader>
I have a query that is working for the most part until I had to add the inner select for "Trainers".
As you can see in the code below, I am trying to get all of the trainers for each of the segment ID's.
I am getting an error on the first inner selects where clause WHERE trn.segmentID = tes.teSegmentID saying that tes.teSegmentID is not defined.
Is there another way to approach this query in order to get the trainers like I am trying to accomplish?
SELECT *,
(SELECT e2.[FirstName] AS trainerFirst,
e2.[LastName] AS trainerLast
FROM BS_Training_Trainers AS trn
LEFT OUTER JOIN
employeeTable AS e2
ON trn.trainerEmpID = e2.EmpID
WHERE trn.segmentID = tes.teSegmentID
FOR XML PATH ('trainer'), TYPE, ELEMENTS, ROOT ('trainers'))
FROM dbo.BS_TrainingEvents AS a
WHERE a.trainingEventID IN (SELECT tes.trainingEventID
FROM dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN
dbo.BS_TrainingEvent_SegmentDetails AS tesd
ON tesd.segmentID = tes.teSegmentID
INNER JOIN
dbo.BS_LocaleCodes AS locale
ON locale.localeID = tesd.localeID
WHERE locale.location = 'Baltimore');
It seems like you're taking the scenic route towards this:
SELECT a.*,
X.[FirstName],
X.[LastName]
FROM dbo.BS_TrainingEvents AS a
LEFT OUTER JOIN (SELECT e2.[FirstName], e2.[LastName], locale.location FROM dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN dbo.BS_Training_Trainers AS trn ON trn.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_TrainingEvent_SegmentDetails AS tesd ON tesd.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_LocaleCodes AS locale ON locale.localeID = tesd.localeID
LEFT OUTER JOIN employeeTable AS e2 ON trn.trainerEmpID = e2.EmpID) AS X ON a.trainingEventID = X.trainingEventID
WHERE X.location = 'Baltimore';
Not sure if I got all those joins right, it was hard to decode from all the nesting you have going on.
If I have guessed table relationships from their names correctly, the only way to solve this is to reference the same filtering condition twice: first, in the XML generation part, and second in the outer level of the query:
with cte as (
select distinct tes.trainingEventID, tes.teSegmentID
from dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN dbo.BS_TrainingEvent_SegmentDetails AS tesd ON tesd.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_LocaleCodes AS locale ON locale.localeID = tesd.localeID
WHERE locale.location = 'Baltimore'
)
SELECT a.*, (
SELECT e2.[FirstName] AS trainerFirst, e2.[LastName] AS trainerLast
FROM BS_Training_Trainers AS trn
LEFT OUTER JOIN employeeTable AS e2 ON trn.trainerEmpID = e2.EmpID
inner join cte c on trn.segmentID = c.teSegmentID
FOR XML PATH ('trainer'), TYPE, ELEMENTS, ROOT ('trainers')
)
FROM dbo.BS_TrainingEvents AS a
where exists (select 0 from cte c where c.testrainingEventID = a.trainingEventID);
It's difficult to tell whether this is completely correct, of course, but I hope you get the idea.
Oh yes, and if you would have an event with multiple Baltimore segments, you will never be able to tell which trainer takes which one. But you can always add more data into XML to resolve this.
Suddenly I cannot find the right way or hint to the solution anywhere, so trying there:
I have a select like this:
declare #XmlOutput xml
set #XmlOutput = (
SELECT
R.ID
,R.[PN] as 'Nummer'
,R.[TitlePrefixAbbreviation] as Title
,R.[FirstName]
,R.LastName
,RA.[DescriptiveNumber]
,RA.[OrientationalNumber]
,RC.Contact
FROM [tbl1] as R
left join tbl2 as RA on R.ID = RA.[RID]
left join [tbl3 as RC on R.ID = RC.[RID]
for xml auto, ROOT('mbox'), ELEMENTS
)
select #XmlOutput
and the result looks like this:
<mbox>
<R>
<ID>66284</ID>
<Nummer>999999</Nummer>
<Title />
<FirstName>test</FirstName>
<LastName>test</LastName>
<RA>
<HouseNr>9999</HouseNr>
<SequenceNr />
<City>London</City>
<ZIP>99999</ZIP>
<RC>
<Contact>letitroll#gmail.com</Contact>
</RC>
</RA>
</R>
<mbox>
As you can see, there are hierarchy elements RA, R, RC that depend on joining tables.
And I cannot find out how to make the XML only with root element <mbox> and without sub tree like R, RC, RA
Something like this ->
<mbox>
<ID>66284</ID>
<Nummer>999999</Nummer>
<Title />
<FirstName>Štěpánka</FirstName>
<LastName>Solomková</LastName>
<HouseNr>2015</HouseNr>
<SequenceNr />
<City>London</City>
<ZIP>99999</ZIP>
<Contact>letitroll#gmail.com</Contact>
<mbox>
I think about a workaround by using temporary table, where i firstly put all selected data, and the generate XML from TMP table, but I hope that there is more elegant way.
Can somebody help ?
Bests,
gelo
declare #XmlOutput xml
set #XmlOutput = (
Select * from
(
SELECT
R.ID
,R.[PN] as 'Nummer'
,R.[TitlePrefixAbbreviation] as Title
,R.[FirstName]
,R.LastName
,RA.[DescriptiveNumber]
,RA.[OrientationalNumber]
,RC.Contact
FROM [tbl1] as R
left join tbl2 as RA on R.ID = RA.[RID]
left join [tbl3 as RC on R.ID = RC.[RID]
) mbox
for xml auto, ELEMENTS
)
select #XmlOutput