TSQL Group By Issue causing duplicates - tsql

I have a query that I created which outputs projects as well as who is presenting the project. My issue is that I am trying to group the presenters to the project ID so it lists the presenters under the project ID and not include it multiple times.
Here is my query:
DECLARE #agendaID AS INT = '23';
SELECT
(SELECT att.empID,
emp.firstName,
emp.lastName,
emp.ntid
FROM dbo.BS_ProjectReview_Attendees AS att
LEFT OUTER JOIN
dbo.EmployeeTable AS emp
ON att.empID = emp.EmpID
WHERE att.agendaID = #agendaID
FOR XML PATH ('attendee'), TYPE, ELEMENTS, ROOT ('attendees')),
(SELECT pres.intID,
int.intTitle,
(SELECT emp.firstName,
emp.lastName,
emp.ntid
FROM dbo.EmployeeTable AS emp
WHERE emp.EmpID = pres.empID
FOR XML PATH ('presenter'), TYPE, ELEMENTS, ROOT ('presenters'))
FROM dbo.BS_ProjectReview_ProjectPresenters AS pres
INNER JOIN dbo.BS_Initiatives AS int
ON pres.intID = int.intID
WHERE pres.agendaID = #agendaID
GROUP BY int.intID <----- ISSUE IS HERE
FOR XML PATH ('project'), TYPE, ELEMENTS, ROOT ('projects'))
FOR XML PATH ('data'), TYPE, ELEMENTS, ROOT ('root');
Here is my XML OUTPUT:
<root>
<data>
<attendees>
<attendee>
<empID>1234</empID>
<firstName>Mike</firstName>
<lastName>Smith</lastName>
<ntid>msmith</ntid>
</attendee>
</attendees>
<projects>
<project>
<intID>202</intID>
<intTitle>Infrastructure Expansion</intTitle>
<presenters>
<presenter>
<firstName>Bob</firstName>
<lastName>Jones</lastName>
<ntid>bjones</ntid>
</presenter>
</presenters>
</project>
<project>
<intID>202</intID>
<intTitle>Infrastructure Expansion</intTitle>
<presenters>
<presenter>
<firstName>User 1</firstName>
<lastName>Last 1</lastName>
<ntid>ulast1</ntid>
</presenter>
</presenters>
</project>
</projects>
</data>
</root>
Here is the desired output:
<root>
<data>
<attendees>
<attendee>
<empID>1234</empID>
<firstName>Mike</firstName>
<lastName>Smith</lastName>
<ntid>msmith</ntid>
</attendee>
</attendees>
<projects>
<project>
<intID>202</intID>
<intTitle>Infrastructure Expansion</intTitle>
<presenters>
<presenter>
<firstName>Bob</firstName>
<lastName>Jones</lastName>
<ntid>bjones</ntid>
</presenter>
<presenter>
<firstName>User 1</firstName>
<lastName>Last 1</lastName>
<ntid>ulast1</ntid>
</presenter>
</presenters>
</project>
</projects>
</data>
</root>
It should be listing both presenters under the same intID however its duplicating them.
I am getting an error with the group by clause as its not contained in an aggregate function and wants me to include pres.empID but then it would not make it unique as they are all different.
Any ideas?

This may be solved using this, however, since SQLFiddle is down ATM, no example.
DECLARE #agendaID AS INT = '23';
SELECT
(SELECT att.empID,
emp.firstName,
emp.lastName,
emp.ntid
FROM dbo.BS_ProjectReview_Attendees AS att
LEFT OUTER JOIN
dbo.EmployeeTable AS emp
ON att.empID = emp.EmpID
WHERE att.agendaID = #agendaID
FOR XML PATH ('attendee'), TYPE, ELEMENTS, ROOT ('attendees')),
(SELECT pres.intID,
int.intTitle,
(SELECT emp.firstName,
emp.lastName,
emp.ntid
FROM dbo.EmployeeTable AS emp
INNER JOIN dbo.BS_ProjectReview_ProjectPresenters AS pres ON emp.EmpID = pres.empID
WHERE pres.intID = int.intID
FOR XML PATH ('presenter'), TYPE, ELEMENTS, ROOT ('presenters'))
FROM dbo.BS_Initiatives AS int
WHERE #agendaID IN ( SELECT pres.agendaID FROM dbo.BS_ProjectReview_ProjectPresenters AS pres WHERE pres.intID = int.intID)
FOR XML PATH ('project'), TYPE, ELEMENTS, ROOT ('projects'))
FOR XML PATH ('data'), TYPE, ELEMENTS, ROOT ('root');

Related

PostgreSQL extract multi value from xml and into columns

I have the below XML in each row with different data.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Declaration xmlns="urn:wco:datamodel:WCO:Declaration_DS:DMS:2" xmlns:ns2="urn:wco:datamodel:WCO:DEC-DMS:2" xmlns:ns3="urn:wco:datamodel:WCO:WCO_DEC_EDS_AUTHORISATION:1">
<ns2:FunctionCode>9</ns2:FunctionCode>
<ns2:ProcedureCategory>B1</ns2:ProcedureCategory>
<ns2:FunctionalReferenceID>LRNU4YZHFFG</ns2:FunctionalReferenceID>
<ns2:IssueDateTime>
<DateTimeString formatCode="304">20210816084322+01</DateTimeString>
</ns2:IssueDateTime>
<ns2:TypeCode>EXA</ns2:TypeCode>
<ns2:GoodsItemQuantity>2</ns2:GoodsItemQuantity>
<ns2:DeclarationOfficeID>ABCd</ns2:DeclarationOfficeID>
<ns2:TotalGrossMassMeasure unitCode="KGM">33000.000</ns2:TotalGrossMassMeasure>
<ns2:TotalPackageQuantity>400</ns2:TotalPackageQuantity>
<ns2:Submitter>
<ns2:Name>ABC</ns2:Name>
<ns2:ID>ABC</ns2:ID>
</ns2:Submitter>
</ns2:Declaration>
ID
messagebody
1
<Xml...
2
<Xml...
what I would like to have is a query that extracts some elements from the XML and put them in a table as below
ID
messagebody
FunctionalReferenceID
ProcedureCategory
1
<Xml...
LRR....
B1
2
<Xml...
LR1....
B2
I'm using the below sql to extract only 1 path
select u.val::text
from sw_customs_message scm
cross join unnest(xpath('//ns2:ProcedureCategory/text()',
scm.messagebody::xml,
array[array['ns2','urn:wco:datamodel:WCO:DEC-DMS:2']])) as u(val)
where u.val::text = 'H7'
How i can use the xmltable() ?
Using xmltable() is typically easier for multiple columns (and rows), especially if namespaces come into play:
select scm.id, mb.*
from sw_customs_message scm
cross join xmltable(xmlnamespaces ('urn:wco:datamodel:WCO:DEC-DMS:2' as ns2,
'urn:wco:datamodel:WCO:WCO_DEC_EDS_AUTHORISATION:1' as ns3),
'/ns2:Declaration'
passing cast(messagebody as xml)
columns
functional_reference_id text path 'ns2:FunctionalReferenceID',
procedure_category text path 'ns2:ProcedureCategory',
function_code int path 'ns2:FunctionCode',
good_items_quantity int path 'ns2:GoodsItemQuantity'
) as mb
where mb.procedure_category = ...
messagebody should really be defined as xml so that you don't need to cast it each time you want to do something with the XML.

Oracle XML DB with XMLEXISTS don't work with xmlns on root XML

I have a table with XMLTYPE column and the XMLEXIST works fine.
But when the root element have a xmlns atribute the XMLEXISTS don't find the record what i'm looking for.
Without the xmlns attribute the XMLEXISTS works fine.
What's wrong?
Example:
<employe>
<employe_id>12345</employe_id>
<employe_name>John</employe_name>
</employe>
The Query:
SELECT count(*) FROM mytable
WHERE XMLEXISTS('/employe[employe_id="12345"]'
PASSING xmltype_col
)
Result: 1
But with xmlns attribute on the root element the query return 0.
<employe xmlns="http://www.example.com/version_01_01_00">
<employe_id>12345</employe_id>
<employe_name>John</employe_name>
</employe>
The mytable is schemaless.
After much research, I discovered the solution.
select *
from (
select
xmlelement("employe",
XMLATTRIBUTES('www.example.com/version_01_01_00' as "xmlns") ,
xmlforest(
'12345' as "employe_id",
'John' as "employe_name"
)
) test
from dual
) x
where XMLEXISTS(
'declare default element namespace "www.example.com/version_01_01_00"; (::)
/employe[employe_id="12345"]'
PASSING test
)

How to integrate WITH Recursive in a Querydsl query

I'm new to Querydsl and I'm struggling to figure out how to implement the following query:
WITH RECURSIVE results AS
(
SELECT id,
parent_id
FROM project
WHERE id = '8a3d6714-27fa-4d1f-962f-9047d616ab42'
UNION ALL
SELECT t.id,
t.parent_id
FROM project t
INNER JOIN results r ON r.parent_id = t.id
)
SELECT *
FROM results;
Its objective is to, starting from the bottom of a hierarchy, collect the anchor's parent (8a3d6714-27fa-4d1f-962f-9047d616ab42 in the above example; there is only one parent per row) all the way up to a point where there is a element without a parent. If successful, using my database, it should yield the following:
id parent_id
------------------------------------ ------------------------------------
8a3d6714-27fa-4d1f-962f-9047d616ab42 babc74e8-1b6f-49e8-a1e3-a176fce2975d
babc74e8-1b6f-49e8-a1e3-a176fce2975d 3f83c9a2-bf43-46d8-bf87-070f5b55ae5a
3f83c9a2-bf43-46d8-bf87-070f5b55ae5a 69c074c6-a329-42c3-8e2e-5da9ab0ef81e
69c074c6-a329-42c3-8e2e-5da9ab0ef81e bccab264-027c-4c4f-9ae8-3409efc6aeb3
bccab264-027c-4c4f-9ae8-3409efc6aeb3 227db39a-2219-4abb-a2a7-3d28bf47ac01
227db39a-2219-4abb-a2a7-3d28bf47ac01
Any thoughts would be much appreciated.
Regards
Rodrigo
QProjects results = new QProjects("results");
QProjects p = new QProjects("p");
QProjects t = new QProjects("t");
String id = "8a3d6714-27fa-4d1f-962f-9047d616ab42";
query.withRecursive(results, subQuery()
.unionAll(
subQuery().from(p).where(p.id.eq(id)).list(p.id, p.parentId),
subQuery().from(t).innerJoin(results).on(results.parentId.eq(t.id)).list(t.id, t.parentId)))
.from(results)
.list(results.id, results.parentId);

How to avoid namespace in child nodes using FOR XML PATH?

I want to create a sitemap xml file (including images) directly from the database without another process (like transformation or another trick).
My query is:
;WITH XMLNAMESPACES(
DEFAULT 'http://www.sitemaps.org/schemas/sitemap/0.9',
'http://www.google.com/schemas/sitemap-image/1.1' as [image] )
SELECT
(SELECT
'mysite' as [loc],
(select
'anotherloc'
as [image:loc]
for XML path('image:image'), type
)
for xml path('url'), type
)
for xml path('urlset'), type
Returns:
<urlset xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<loc>mysite</loc>
<image:image xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<image:loc>anotherloc</image:loc>
</image:image>
</url>
</urlset>
But I need this output, without repeated namespace declaration:
<urlset xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>mysite</loc>
<image:image>
<image:loc>anotherloc</image:loc>
</image:image>
</url>
</urlset>
I'm sure you realise that the additional otiose namespace declarations don't change the meaning of the XML document, so if the result is going to be consumed by an XML-conformant tool, they shouldn't matter. Nevertheless I know there are some tools out there which don't do XML Namespaces correctly, and in a large XML instance superfluous repeated namespace declarations can bloat the size of the result significantly, which may cause its own problems.
In general there is no getting around the fact that each SELECT...FOR XML statement within the scope of a WITH XMLNAMESPACES prefix will generate namespace declarations on the outermost XML element(s) in its result set, in all XML-supporting versions of SQL Server up to SQL Server 2012.
In your specific example, you can get fairly close to the desired XML by separating the SELECTs rather than nesting them, and using the ROOT syntax for the enveloping root element, thus:
DECLARE #inner XML;
WITH XMLNAMESPACES('http://www.google.com/schemas/sitemap-image/1.1' as [image])
SELECT #inner =
(
SELECT
'anotherloc' AS [image:loc]
FOR XML PATH('image:image'), TYPE
)
;WITH XMLNAMESPACES(
DEFAULT 'http://www.sitemaps.org/schemas/sitemap/0.9'
)
SELECT
'mysite' AS [loc],
#inner
FOR XML PATH('url'), ROOT('urlset'), TYPE
The result being:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>mysite</loc>
<image:image xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="">
<image:loc>anotherloc</image:loc>
</image:image>
</url>
</urlset>
But this approach doesn't provide a completely general solution to the problem.
You can use UDF. Example:
ALTER FUNCTION [dbo].[udf_get_child_section] (
#serviceHeaderId INT
)
RETURNS XML
BEGIN
DECLARE #result XML;
SELECT #result =
(
SELECT 1 AS 'ChildElement'
FOR XML PATH('Child')
)
RETURN #result
END
GO
DECLARE #Ids TABLE
(
ID int
)
INSERT INTO #Ids
SELECT 1 AS ID
UNION ALL
SELECT 2 AS ID
;WITH XMLNAMESPACES (DEFAULT 'http://www...com/content')
SELECT
[dbo].[udf_get_child_section](ID)
FROM
#Ids
FOR XML PATH('Parent')
Result:
<Parent xmlns="http://www...com/content">
<Child xmlns="">
<ChildElement>1</ChildElement>
</Child>
</Parent>
<Parent xmlns="http://www...com/content">
<Child xmlns="">
<ChildElement>1</ChildElement>
</Child>
</Parent>
Maybe too late for answer, but this is a quick solution.
`DECLARE #PageNumber Int = 1;
DECLARE #siteMapXml XML ;
;WITH XMLNAMESPACES (
'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd' as "schemaLocation",
'http://www.w3.org/2001/XMLSchema-instance' as xsi,
'http://www.google.com/schemas/sitemap-image/1.1' as [image],
DEFAULT 'http://www.sitemaps.org/schemas/sitemap/0.9'
)
SELECT #siteMapXml = (
SELECT
Slug loc,
convert(varchar(300),[Image]) as [image:image/image:loc]
,
Convert(char(10), UpdatedOnUtc, 126) as lastmod,
'hourly' as changefreq,
'0.5' as priority
FROM Products(NOLOCK)
WHERE Pagenumber = #PageNumber
FOR XML PATH ('url'), ROOT ('urlset'))
SELECT #siteMapXml = REPLACE(CAST(#siteMapXml AS NVARCHAR(MAX)), ' xmlns:schemaLocation=', ' xsi:schemaLocation=')
SELECT #siteMapXml`

Why is this field not showing up in the results?

When I run the selects below, I do not get Field3 in the result set, why?
Select
a.Field1,
a.Field2,
a.Field3,
sum(IsNull(a.Field4, 0)) AS SomeAlias1,
a.SomeField5,
a.SomeField6,
a.SomeField7
From SomeTable a
INNER JOIN SomeView1 v on v.au = a.au
inner join (select Username, House from Users userBuildings where UserName = #UserName) as userHouses on userHouses.au = a.au
WHERE
(((where claus logic here....
Group BY a.Field1,
a.Field2,
a.SomeAlias1,
a.Field3,
a.Field4,
a.Field5,
a.Field6,
a.Fielf7
)
Select
transBudget.Field1,
transBudget.Field2,
transDiscount.Field4,
... some other fields...
IsNull(transDiscount.Actual, 0) - IsNull(transBudget.Actual, 0) AS Variance
from (Select * from Transactdions Where TransDesc = 'Budget') AS transBudget
FULL OUTER JOIN
(Select * from Transactions Where TransDesc = 'Discount') AS transDiscount
ON transBudget.Market = transDiscount.Market AND transBudget.SubMarket = transDiscount.SubMarket
I see every field except Field3 for some reason and it's beyond me how the heck this can happen.
In the second part of your query, you are missing field 3.
Select
transBudget.Field1,
transBudget.Field2,
transDiscount.Field4,
... some other fields...
IsNull(transDiscount.Actual, 0)
You appear to have two separate SQL queries there. The first one contains Field3, but the second one does not.