Am Montag, 19. Dezember 2022 um 23:48:45 MEZ hat Imsieke, Gerrit, le-tex <gerrit.imsieke@le-tex.de> Folgendes geschrieben:
Thank you, Hans-Jürgen, for shedding really insightful light (if there
is such a thing) on this aspect of XQuery grouping, which I use
gropingly (pun intended) without fully understanding it.
On 19.12.2022 23:19, Hans-Juergen Rennau wrote:
> I think the reason is a different one - it is related to the precise
> semantics of the group by clause.
>
> The group by clause maps each group of input tuples with equal grouping
> key(s) to a single output tuple, in which
> - the grouping variable(s) is/are bound to the key values (as you would
> expect)
> - all other variables are bound to the concatenated sequence of values
> bound to the variable name in the members of the group (which may cause
> surprises)
>
> So when a group has, say, 3 members, the variable $organisations is not
> any more bound to a single function item, but to a sequence of 3
> function items (which are identical). Of course, a sequence of more than
> one function item cannot be called - only a single function item can be
> called. In order to check that this is the correct interpretation of the
> issue, you can remove the second assignment to $organisations, and
> append to the invocation the predicate [1] - then it works, as then you
> have again a single function item:
>
> <country>{$country/@name, $organizations[1]($country)}</country>
>
> One way to handle this in a more straightforward way is to shift the
> function item into an additional, outer FLWOR level at the beginning.
> While we are at it, let's shift both function items:
>
> let $organizations := function($country){
> $doc//organization[members/@country = $country/@id]/@abbrev/string(.)}
> let $membershipPotentcy := function($orgs){
> if (count($orgs)le 0) then 'none' else if (count($orgs) le 5) then
> 'few' else 'many'}
> return
> element Memberships {
> for $countries in $doc//country
> group by $mp:= $membershipPotentcy($organizations($countries))
> order by $mp
> return
> element {$mp} {
> for $country in $countries
> return
> <country>{$country/@name, $organizations($country)}</country>
> }}
>
>
> Am Montag, 19. Dezember 2022 um 22:58:30 MEZ hat Graydon
>
>
> On Mon, Dec 19, 2022 at 10:43:25PM +0100, Leo Studer scripsit:
>
> > In the code below I encounter the problem, that I have to define the
> same xPath function variable $organizations twice and I do not
> understand why.
>
>
> In line 10, you've used a let clause to bind a variable of type function
> to the name organizations. That's in context a specific FLOWR expression.
>
> The expression in the return clause of that FLOWR expression returns an
> element constructor where the contents expression contains another FLOWR
> expression. The first definition on line 10 will be out of scope in
> there.
>
> You could define the function with scope for the module:
>
> declare function local:getOrganizations($in as element(country))
> as xs:string* {
> let $thisCountry as xs:string := $in/@id/string();
> return $doc//organization[members/@country =
> $thisCountry]/@abbrev/string(.)
> };
>
> And then use it in both places with the single definition.
>
>
> --
> Þæs oferéode, ðisses swá mæg.
> -- Deor ("That passed, so may this.")
>
>