Skip to content

Commit

Permalink
groupby with rolluprecursive ordered like simple grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
HeikoTheissen committed Jun 30, 2023
1 parent af56033 commit 8ce6813
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2949,11 +2949,12 @@ <h2 id="63-grouping-with-rolluprecursive"><a name="Groupingwithrolluprecursive"
<p>Let <span class="math inline">\(T\)</span> be a transformation sequence, <span class="math inline">\(P_1\)</span> stand in for zero or more property paths and <span class="math inline">\(P_2\)</span> for zero or more <code>rollup</code> or <code>rolluprecursive</code> operators or property paths. The transformation <span class="math inline">\({\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)\)</span> is computed by the following algorithm, which invokes itself recursively if the number of <code>rolluprecursive</code> operators in the first argument of the <code>groupby</code> transformation, which is called <span class="math inline">\(M\)</span>, is greater than one. Let <span class="math inline">\(N\)</span> be the recursion depth of the algorithm, starting with 1.</p>
<p><em>The <code>rolluprecursive</code> algorithm:</em></p>
<p>A property <span class="math inline">\(χ_N\)</span> appears in the algorithm, but is not present in the output set. It is explained later (see <a href="#rollupnode">example 66</a>). <span class="math inline">\(Z_N\)</span> is a transformation whose output set is its input set with property <span class="math inline">\(χ_N\)</span> removed.</p>
<p>Let <span class="math inline">\(x_1,…,x_n\)</span> be the nodes in <span class="math inline">\(H&#39;\)</span>, possibly with repetitions. If the optional transformation sequence <span class="math inline">\(S\)</span> ends with a <a href="#Transformationtraverse"><code>traverse</code></a> transformation, as in <a href="#weighted">example 118</a>, the sequence <span class="math inline">\(x_1,…,x_n\)</span> MUST have the preorder or postorder established by that traversal, otherwise its order is arbitrary. Then the transformation <span class="math inline">\({\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)\)</span> is defined as equivalent to <span class="math display">\[{\tt concat}(R(x_1),…,R(x_n))\]</span> with no order defined on the output set unless <span class="math inline">\(S\)</span> ends with a <code>traverse</code> transformation.</p>
<p>Let <span class="math inline">\(x_1,…,x_n\)</span> be the nodes in <span class="math inline">\(H&#39;\)</span>, possibly with repetitions. If the optional transformation sequence <span class="math inline">\(S\)</span> ends with a <a href="#Transformationtraverse"><code>traverse</code></a> transformation, as in <a href="#weighted">example 118</a>, the sequence <span class="math inline">\(x_1,…,x_n\)</span> MUST have the preorder or postorder established by that traversal, and the transformation <span class="math inline">\({\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)\)</span> is defined as equivalent to <span class="math display">\[{\tt concat}(R(x_1),…,R(x_n)).\]</span></p>
<p>Otherwise, if <span class="math inline">\(S\)</span> is not specified or does not end with a <code>traverse</code> transformation, the output set of the transformation <span class="math inline">\({\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)\)</span> is the concatenation of <span class="math inline">\(R(x_1),…,R(x_n)\)</span>. The order of occurrences from the same <span class="math inline">\(R(x_i)\)</span> remains the same, and no order is defined between occurrences from different <span class="math inline">\(R(x_i)\)</span> and <span class="math inline">\(R(x_j)\)</span>.</p>
<p><span class="math inline">\(R(x)\)</span> is a transformation that processes the entire sub-hierarchy rooted at <span class="math inline">\(x\)</span>, which is the output set of <span class="math inline">\(F(x)\)</span>. The output set of <span class="math inline">\(R(x)\)</span> is a collection of aggregated instances for all rollup results.</p>
<p>If at least one of <span class="math inline">\(P_1\)</span> or <span class="math inline">\(P_2\)</span> is non-empty, then <span class="math display">\[R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x)))\]</span> with no order defined on the output set.</p>
<p>If at least one of <span class="math inline">\(P_1\)</span> or <span class="math inline">\(P_2\)</span> is non-empty, then <span class="math display">\[R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x))).\]</span></p>
<p>The property <span class="math inline">\(χ_N=x\)</span> is present during the evaluation of <span class="math inline">\(T\)</span>, but not afterwards. If <span class="math inline">\(P_2\)</span> contains a <code>rolluprecursive</code> operator, the evaluation of the formula involves a recursive invocation (with <span class="math inline">\(N\)</span> increased by 1) of the <code>rolluprecursive</code> algorithm.</p>
<p>Otherwise if <span class="math inline">\(P_1\)</span> and <span class="math inline">\(P_2\)</span> are empty, then <span class="math display">\[R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x))\]</span> with no order defined on the output set.</p>
<p>Otherwise if <span class="math inline">\(P_1\)</span> and <span class="math inline">\(P_2\)</span> are empty, then <span class="math display">\[R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x)).\]</span></p>
<p><span class="math inline">\(F(x)\)</span> is defined as follows: If <span class="math inline">\(p\)</span> contains only single-valued segments, then <span class="math display">\[\matrix{ F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{&#39;$Q$&#39;}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill }\]</span></p>
<p>Otherwise <span class="math inline">\(p=p_1/…/p_k/r\)</span> with <span class="math inline">\(k≥1\)</span> and <span class="math display">\[\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{&#39;$Q$&#39;}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }\]</span> where <span class="math inline">\(y_1,…,y_k\)</span> denote <code>lambdaVariableExpr</code>s and <span class="math inline">\({}/r\)</span> may be absent. (See <a href="#rollupcoll">example 113</a> for a case with <span class="math inline">\(k=1\)</span>.)</p>
<p>Informatively speaking, the effect of the algorithm can be summarized as follows: If <span class="math inline">\(M≥1\)</span> and <span class="math inline">\(\hat F_N(x)\)</span> denotes the collection of all instances that are related to a node <span class="math inline">\(x\)</span> as determined by <span class="math inline">\(F(x)\)</span> in the recursive hierarchy of the <span class="math inline">\(N\)</span>-th <code>rolluprecursive</code> operator, then <span class="math inline">\(T\)</span> is applied to each of the intersections of <span class="math inline">\(\hat F_1(χ_1),…,\hat F_M(χ_M)\)</span>, as <span class="math inline">\(χ_N\)</span> runs over all nodes of the <span class="math inline">\(N\)</span>-th recursive hierarchy for <span class="math inline">\(1≤N≤M\)</span>. Into the instances of the resulting output sets the <span class="math inline">\(\Pi_G\)</span> transformations inject information about the nodes <span class="math inline">\(χ_1,…,χ_M\)</span>.</p>
Expand Down
13 changes: 6 additions & 7 deletions docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
Original file line number Diff line number Diff line change
Expand Up @@ -2974,21 +2974,20 @@ _The `rolluprecursive` algorithm:_

A property $χ_N$ appears in the algorithm, but is not present in the output set. It is explained later (see [example 66](#rollupnode)). $Z_N$ is a transformation whose output set is its input set with property $χ_N$ removed.

Let $x_1,…,x_n$ be the nodes in $H'$, possibly with repetitions. If the optional transformation sequence $S$ ends with a [`traverse`](#Transformationtraverse) transformation, as in [example 118](#weighted), the sequence $x_1,…,x_n$ MUST have the preorder or postorder established by that traversal, otherwise its order is arbitrary. Then the transformation ${\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)$ is defined as equivalent to
$${\tt concat}(R(x_1),…,R(x_n))$$
with no order defined on the output set unless $S$ ends with a `traverse` transformation.
Let $x_1,…,x_n$ be the nodes in $H'$, possibly with repetitions. If the optional transformation sequence $S$ ends with a [`traverse`](#Transformationtraverse) transformation, as in [example 118](#weighted), the sequence $x_1,…,x_n$ MUST have the preorder or postorder established by that traversal, and the transformation ${\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)$ is defined as equivalent to
$${\tt concat}(R(x_1),…,R(x_n)).$$

Otherwise, if $S$ is not specified or does not end with a `traverse` transformation, the output set of the transformation ${\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)$ is the concatenation of $R(x_1),…,R(x_n)$. The order of occurrences from the same $R(x_i)$ remains the same, and no order is defined between occurrences from different $R(x_i)$ and $R(x_j)$.

$R(x)$ is a transformation that processes the entire sub-hierarchy rooted at $x$, which is the output set of $F(x)$. The output set of $R(x)$ is a collection of aggregated instances for all rollup results.

If at least one of $P_1$ or $P_2$ is non-empty, then
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x)))$$
with no order defined on the output set.
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x))).$$

The property $χ_N=x$ is present during the evaluation of $T$, but not afterwards. If $P_2$ contains a `rolluprecursive` operator, the evaluation of the formula involves a recursive invocation (with $N$ increased by 1) of the `rolluprecursive` algorithm.

Otherwise if $P_1$ and $P_2$ are empty, then
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x))$$
with no order defined on the output set.
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x)).$$

$F(x)$ is defined as follows: If $p$ contains only single-valued segments, then
$$\matrix{ F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill }$$
Expand Down
Binary file modified docs/odata-data-aggregation-ext/odata-data-aggregation-ext.pdf
Binary file not shown.
13 changes: 6 additions & 7 deletions odata-data-aggregation-ext/6 Hierarchical Transformations.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,21 +356,20 @@ _The `rolluprecursive` algorithm:_

A property $χ_N$ appears in the algorithm, but is not present in the output set. It is explained later (see [example ##rollupnode]). $Z_N$ is a transformation whose output set is its input set with property $χ_N$ removed.

Let $x_1,…,x_n$ be the nodes in $H'$, possibly with repetitions. If the optional transformation sequence $S$ ends with a [`traverse`](#Transformationtraverse) transformation, as in [example ##weighted], the sequence $x_1,…,x_n$ MUST have the preorder or postorder established by that traversal, otherwise its order is arbitrary. Then the transformation ${\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)$ is defined as equivalent to
$${\tt concat}(R(x_1),…,R(x_n))$$
with no order defined on the output set unless $S$ ends with a `traverse` transformation.
Let $x_1,…,x_n$ be the nodes in $H'$, possibly with repetitions. If the optional transformation sequence $S$ ends with a [`traverse`](#Transformationtraverse) transformation, as in [example ##weighted], the sequence $x_1,…,x_n$ MUST have the preorder or postorder established by that traversal, and the transformation ${\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)$ is defined as equivalent to
$${\tt concat}(R(x_1),…,R(x_n)).$$

Otherwise, if $S$ is not specified or does not end with a `traverse` transformation, the output set of the transformation ${\tt groupby}((P_1,{\tt rolluprecursive}(H,Q,p,S),P_2),T)$ is the concatenation of $R(x_1),…,R(x_n)$. The order of occurrences from the same $R(x_i)$ remains the same, and no order is defined between occurrences from different $R(x_i)$ and $R(x_j)$.

$R(x)$ is a transformation that processes the entire sub-hierarchy rooted at $x$, which is the output set of $F(x)$. The output set of $R(x)$ is a collection of aggregated instances for all rollup results.

If at least one of $P_1$ or $P_2$ is non-empty, then
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x)))$$
with no order defined on the output set.
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x))).$$

The property $χ_N=x$ is present during the evaluation of $T$, but not afterwards. If $P_2$ contains a `rolluprecursive` operator, the evaluation of the formula involves a recursive invocation (with $N$ increased by 1) of the `rolluprecursive` algorithm.

Otherwise if $P_1$ and $P_2$ are empty, then
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x))$$
with no order defined on the output set.
$$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x)).$$

$F(x)$ is defined as follows: If $p$ contains only single-valued segments, then
$$\matrix{
Expand Down

0 comments on commit 8ce6813

Please sign in to comment.