Hans-Juergen, thanks for this insight, that sheds even more light for me into the grouping with xquery...

On 20 Dec 2022, at 08:42, Hans-Juergen Rennau <hrennau@yahoo.de> wrote:

Thank you for your kind words, Gerrit! Until a few weeks ago, my use of grouping was a groping one also in my case - until I learned from the spec that the FLWOR mechanics are only fully understood if we regard the clauses as a pipeline of stations, each one transforming an input tuple stream into an output tuple stream - that's the key. And that's at first weird, as we are used to think in terms of "assignments", "loops", sorting, grouping, filtering, counting devices. But when thinking of the different clauses as just variants of a single idea - "tuple stream transformer" - everything is decomposed into tiny bits - the details of how a particular kind of clause maps its input tuples to output tuples. No interaction whatsoever between the clauses, apart from output tuple streams becoming input tuple streams. Suddenly it is not amazing any more that you can have any number of any kind of clauses, e.g. several where clauses, and that the clauses can occur at any position within the expression (except for the constraint that the first clause must be let or for). And so, for example, I had always kept my fingers crossed when adding an order by after a group by. Now I understand that once the group by has done its thing and produced an output tuple stream according to its rules, you have a tuple stream without any memory of what has happened at earlier clauses.

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
> <graydonish@gmail.com> Folgendes geschrieben:
>
>
> 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.
>
>
> --
> Graydon Saunders  | graydonish@gmail.com <mailto:graydonish@gmail.com>
> Þæs oferéode, ðisses swá mæg.
> -- Deor  ("That passed, so may this.")
>
>