SQL Server and XML query - sql-server

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

Related

how to using distinct in XML SQL using stored procedure

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
)

Any other ways to change "With As" for mariadb

WITH KPILibHier (kpilib_code,parent_code,kpi_name, depth, iscategory)
AS ( SELECT K.kpilib_code, K.parent_code, K.kpi_name_en, K.kpi_depth, K.iscategory
FROM TPMDPERIODKPILIB K
INNER JOIN TPMDPERIODKPI PK ON PK.period_code = K.period_code
UNION ALL
SELECT A.kpilib_code, A.parent_code, A.kpi_name_en, A.kpi_depth, A.iscategory
FROM TPMDPERIODKPILIB A
INNER JOIN KPILibHier AS B ON A.kpilib_code = B.parent_code )
SELECT DISTINCT Z.kpi_name AS libname, Z.kpilib_code AS libcode,
Z.parent_code AS pcode, Z.depth, Z.iscategory, PK.target
FROM KPILibHier Z
LEFT JOIN TPMDPERIODKPILIB KPI
ON KPI.kpilib_code = Z.kpilib_code
LEFT JOIN TPMDPERIODKPI PK
ON PK.period_code = KPI.period_code
ORDER BY Z.depth, Z.kpi_name
This is my code.
I could run it in SQL Server,
But now i have to use Mariadb,
and Mariadb doesn't use "WITH AS".
So is there any other way to change this code for the same result?
As we can see, there's "INNER JOIN KPILibHier" too inside the CTE,
So I couldn't make ordinary subquery as usual.
Just moving the contents of the CTE to a derived table should provide something usable. Something like;
SELECT DISTINCT Z.kpi_name AS libname, Z.kpilib_code AS libcode,
Z.parent_code AS pcode, Z.depth, Z.iscategory, PK.target
FROM
( SELECT K.kpilib_code, K.parent_code, K.kpi_name_en AS kpi_name, K.kpi_depth AS depth, K.iscategory
FROM TPMDPERIODKPILIB K
INNER JOIN TPMDPERIODKPI PK ON PK.period_code = K.period_code
UNION ALL
SELECT A.kpilib_code, A.parent_code, A.kpi_name_en, A.kpi_depth, A.iscategory
FROM TPMDPERIODKPILIB A
) z
INNER JOIN z AS B ON A.kpilib_code = B.parent_code
LEFT JOIN TPMDPERIODKPILIB KPI
ON KPI.kpilib_code = Z.kpilib_code
LEFT JOIN TPMDPERIODKPI PK
ON PK.period_code = KPI.period_code
ORDER BY Z.depth, Z.kpi_name

TSQL select from XML

I have a stored procedure that looks like the following:
SELECT
ParamValues.x1.value('likeID[1]', 'VARCHAR(60)'),
COUNT(B.[userID]) AS totalLikes
FROM
#likeXML.nodes('/likes/like') AS ParamValues(x1)
JOIN
apsLikes AS B ON B.[likeID] = ParamValues.x1.value('likeID[1]', 'VARCHAR(60)')
FOR XML PATH ('likeData'), TYPE, ELEMENTS, ROOT ('root');
However this returns an error
Column 'ParamValues.x1' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
When I try and add it to the group by it says XML cannot be used in the group by clause.
What would be the correct way to format this?
Have you tried maybe using a CTE? Give the first column an alias, and remove the COUNT... like this:
; WITH XmlResults AS (
SELECT
ParamValues.x1.value('likeID[1]', 'VARCHAR(60)') AS likeId,
B.[userID] AS totalLikes
FROM
#likeXML.nodes('/likes/like') AS ParamValues(x1)
JOIN
apsLikes AS B ON B.[likeID] = ParamValues.x1.value('likeID[1]', 'VARCHAR(60)')
FOR XML PATH ('likeData'), TYPE, ELEMENTS, ROOT ('root')
)
SELECT likeId, COUNT(totalLikes)
FROM XmlResults
GROUP BY likeId
One of the ways is to do a nested select, like this:
SELECT LikeId, COUNT(Userid) FROM (
SELECT ParamValues.x1.value('likeID[1]', 'VARCHAR(60)') LikeId,
B.[userID] Userid
FROM #likeXML.nodes('/likes/like') AS ParamValues(x1)
JOIN apsLikes AS B
ON B.[likeID] = ParamValues.x1.value('likeID[1]', 'VARCHAR(60)')
FOR XML PATH ('likeData'), TYPE, ELEMENTS, ROOT ('root');
) tmp
Group By LikeId
Making a subquery and then grouping and XML'it should work :
select x1, count(Likes) from
(
SELECT
ParamValues.x1.value('likeID[1]', 'VARCHAR(60)') AS X1,
B.[userID] AS Likes
FROM
#likeXML.nodes('/likes/like') AS ParamValues(x1)
JOIN
apsLikes AS B ON B.[likeID] = ParamValues.x1.value('likeID[1]', 'VARCHAR(60)')
) t
group by X1
FOR XML PATH ('likeData'), TYPE, ELEMENTS, ROOT ('root');

LEFT JOIN with FOR XML AUTO, ELEMENTS

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')

SQL Subquery Select Table based on Outer Query

I have a general query that looks like this:
SELECT DISTINCT pb.id, pb.last, pb.first, pb.middle, pb.sex, pb.phone, pb.type,
specialties = substring(
SELECT ('|' + cs.specialty )
FROM CertSpecialty AS cs
INNER JOIN CertSpecialtyIndex AS csi on cs.specialty = csi.specialty
WHERE cs.id = pb.id
ORDER BY cs.sequence_no
FOR XML path(''),2,500)
FROM table AS pb
WHERE etc etc etc
The issue is this:
The "type" column that I'm selecting is an integer - types 1-4.
In the subquery, see where I am querying from the table CertSpecialty right now.
What I actually need to do is, if the type field comes back as a 1 or a 3, that's the table I need to query. But if the row's result is a type 2 or 4 (i.e., an ELSE), I need to be querying the same column in the table CertSpecialtyOther.
So it'd need to look something like this (though this obv doesn't work):
SELECT DISTINCT pb.id, pb.last, pb.first, pb.middle, pb.sex, pb.phone, pb.type,
specialties =
IF type in (1,3)
substring((SELECT ('|' + cs.specialty )
FROM CertSpecialty AS cs
INNER JOIN CertSpecialtyIndex AS csi on cs.specialty = csi.specialty
WHERE cs.id = pb.id
ORDER BY cs.sequence_no
FOR XML path(''),2,500)
ELSE
substring((SELECT ('|' + cs.specialty )
FROM CertSpecialtyOther AS cs
INNER JOIN CertSpecialtyIndex AS csi on cs.specialty = csi.specialty
WHERE cs.id = pb.id
ORDER BY cs.sequence_no
FOR XML path(''),2,500)
end
FROM table AS pb
WHERE etc etc etc
Is this possible? If so, what is the correct syntax? Is there a simpler way to write it where I'm switching which table I query without completely duplicating the subquery?
Also, does anyone have a good resource they could link me for this sort of thing to learn more besides?
Thanks in advance.
Use a CTE.
;WITH cs AS
(
SELECT 'A' SpecialtyCategory, phy_key, specialty
FROM CertSpecialty
UNION ALL
SELECT 'B' SpecialtyCategory, phy_key, specialty
FROM CertSpecialtyOther
)
SELECT csi.id, cs.specialty
FROM cs
INNER JOIN CertSpecialtyIndex AS csi on cs.specialty = csi.specialty
WHERE cs.phy_key = pb.phy_key
AND cs.SpecialtyCategory = (CASE WHEN type in (1,3) THEN 'A' ELSE 'B' END)

Resources