Part #3. Grouping by 3 fields.
Yesterday we managed to group data by two fields. Today I needed to be able to group data by 3 fields. The third field I want to group by the status of the enquiry.
In SQL
SELECT
group_name as `group`,
service_description as `service`,
status as 'status',
count(*) as `enquiry_count`
FROM
enquiry
GROUP BY
group_name,
service_description,
status
</pre><BR><BR>Based upon Thorsten's tips yesterday this is a very trivial task. The XQUERY to group by the additional element is:<BR><BR><pre class="ip-ubbcode-code-pre">
for $group in distinct-values(input()/enquiry/group-name)
for $service in distinct-values(input()/enquiry/service-description)
for $statusdesc in distinct-values(input()/enquiry/status)
let $partition := input()/enquiry[group-name = $group and service-description = $service and status = $statusdesc]
let $svccount := count($partition)
where $partition and $svccount != 0
return
<row>
<group>{$group}</group>
<service>{$service}</service>
<status>{$statusdesc}</status>
<enquiry-count>{$svccount}</enquiry-count>
</row>
</pre><BR><BR>This would give us the following output:<BR><BR><pre class="ip-ubbcode-code-pre">
<row>
<group>General</group>
<service>applications</service>
<status>open</status>
<enquiry-count>2</enquiry-count>
</row>
<row>
<group>General</group>
<service>finance</service>
<status>closed</status>
<enquiry-count>1</enquiry-count>
</row>
<row>
<group>General</group>
<service>finance</service>
<status>open</status>
<enquiry-count>5</enquiry-count>
</row>
<row>
<group>Departments</group>
<service>finance</service>
<status>open</status>
<enquiry-count>1</enquiry-count>
</row>
<row>
<group>General</group>
<service>applications</service>
<status>closed</status>
<enquiry-count>2</enquiry-count>
</row>
</pre><BR><BR>So far so good. The only problem you will notice with the results is that they are not ordered as they would be from a SQL database. Without us saying so the SQL will automatically keep fields ordered by group, service and then status. <BR><BR>In my case this order is important as the results will be fed into a reporting tool.<BR><BR>I believe Tamino is not doing this as the query has to 'join' the data back together by the 3 sets of distinct values (which are not retrieved in any specific order). To ensure the data is returned in the order expected the query should be changed to include a <B>sort by</B> operation like so:<BR><BR><pre class="ip-ubbcode-code-pre">
for $group in distinct-values(input()/enquiry/group-name)
for $service in distinct-values(input()/enquiry/service-description)
for $statusdesc in distinct-values(input()/enquiry/status)
let $partition := input()/enquiry[group-name = $group and service-description = $service and status = $statusdesc]
let $svccount := count($partition)
where $partition and $svccount != 0
return
<row>
<group>{$group}</group>
<service>{$service}</service>
<status>{$statusdesc}</status>
<enquiry-count>{$svccount}</enquiry-count>
</row>
sort by (group, service, status)
There is no noticeable difference in performance after this change. As always - to help query performance insure the element you intend to group by has a standard index defined.
Tomorrow I will take the above query and filter the results on enquries between given a given start and end date.
Regards
Ian Gratton
#webMethods#Tamino#API-Management