This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/incubator-age-website.git
The following commit(s) were added to refs/heads/asf-site by this push:
new d71b426 deploy: bf32017e0dfc2804fa9da06deaf36481ed84aadb
d71b426 is described below
commit d71b426f4217638b9904cd0ef355ed8ee45b2651
Author: JoshInnis <[email protected]>
AuthorDate: Thu Oct 21 23:04:20 2021 +0000
deploy: bf32017e0dfc2804fa9da06deaf36481ed84aadb
---
docs/master/.buildinfo | 2 +-
docs/master/.doctrees/advanced/advanced.doctree | Bin 17332 -> 17332 bytes
.../.doctrees/advanced/advanced_overview.doctree | Bin 3665 -> 3665 bytes
docs/master/.doctrees/advanced/plpgsql.doctree | Bin 4203 -> 4203 bytes
.../.doctrees/advanced/prepared_statements.doctree | Bin 8572 -> 8572 bytes
.../.doctrees/advanced/sql_in_cypher.doctree | Bin 5905 -> 5905 bytes
docs/master/.doctrees/clauses/create.doctree | Bin 20453 -> 20453 bytes
docs/master/.doctrees/clauses/delete.doctree | Bin 11208 -> 11208 bytes
docs/master/.doctrees/clauses/limit.doctree | Bin 7427 -> 7427 bytes
docs/master/.doctrees/clauses/match.doctree | Bin 25090 -> 25090 bytes
docs/master/.doctrees/clauses/order_by.doctree | Bin 15347 -> 15347 bytes
docs/master/.doctrees/clauses/remove.doctree | Bin 6630 -> 6630 bytes
docs/master/.doctrees/clauses/return.doctree | Bin 21591 -> 21591 bytes
docs/master/.doctrees/clauses/set.doctree | Bin 11952 -> 11952 bytes
docs/master/.doctrees/clauses/skip.doctree | Bin 9537 -> 9537 bytes
docs/master/.doctrees/clauses/with.doctree | Bin 11085 -> 11085 bytes
docs/master/.doctrees/environment.pickle | Bin 123026 -> 127812 bytes
.../functions/aggregate_functions.doctree | Bin 55961 -> 57732 bytes
.../.doctrees/functions/list_functions.doctree | Bin 2677 -> 2677 bytes
.../functions/logarithmic_functions.doctree | Bin 16358 -> 16358 bytes
.../.doctrees/functions/numeric_functions.doctree | Bin 22664 -> 22664 bytes
.../functions/predicate_functions.doctree | Bin 6445 -> 6445 bytes
.../.doctrees/functions/scalar_functions.doctree | Bin 56524 -> 56524 bytes
.../.doctrees/functions/string_functions.doctree | Bin 47951 -> 47951 bytes
.../functions/trigonometric_functions.doctree | Bin 34627 -> 34627 bytes
.../.doctrees/functions/user_functions.doctree | Bin 4976 -> 4976 bytes
docs/master/.doctrees/index.doctree | Bin 4123 -> 4123 bytes
docs/master/.doctrees/intro/aggregation.doctree | Bin 6801 -> 27595 bytes
docs/master/.doctrees/intro/comparability.doctree | Bin 32235 -> 32235 bytes
docs/master/.doctrees/intro/cypher.doctree | Bin 10246 -> 10246 bytes
docs/master/.doctrees/intro/graphs.doctree | Bin 11554 -> 11554 bytes
docs/master/.doctrees/intro/overview.doctree | Bin 4006 -> 4006 bytes
docs/master/.doctrees/intro/precedence.doctree | Bin 6872 -> 6872 bytes
docs/master/.doctrees/intro/setup.doctree | Bin 11024 -> 11024 bytes
docs/master/.doctrees/intro/types.doctree | Bin 81184 -> 81184 bytes
.../_sources/functions/aggregate_functions.md.txt | 23 +-
docs/master/_sources/intro/aggregation.md.txt | 308 ++++++++++++++++++++-
.../master/_static/functions/aggregation_setup.sql | 18 ++
docs/master/functions/aggregate_functions.html | 25 +-
docs/master/intro/aggregation.html | 281 ++++++++++++++++++-
docs/master/searchindex.js | 2 +-
41 files changed, 642 insertions(+), 17 deletions(-)
diff --git a/docs/master/.buildinfo b/docs/master/.buildinfo
index 2ffacee..8211b42 100644
--- a/docs/master/.buildinfo
+++ b/docs/master/.buildinfo
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it
is not found, a full rebuild will be done.
-config: 734c5355eed7012d68f5fb5f87a322c9
+config: ad541acc25c98ff5f503246f6387aa31
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/master/.doctrees/advanced/advanced.doctree
b/docs/master/.doctrees/advanced/advanced.doctree
index 5306976..fcea03e 100644
Binary files a/docs/master/.doctrees/advanced/advanced.doctree and
b/docs/master/.doctrees/advanced/advanced.doctree differ
diff --git a/docs/master/.doctrees/advanced/advanced_overview.doctree
b/docs/master/.doctrees/advanced/advanced_overview.doctree
index 7ff439c..f6a7e41 100644
Binary files a/docs/master/.doctrees/advanced/advanced_overview.doctree and
b/docs/master/.doctrees/advanced/advanced_overview.doctree differ
diff --git a/docs/master/.doctrees/advanced/plpgsql.doctree
b/docs/master/.doctrees/advanced/plpgsql.doctree
index 6f9fe70..389e828 100644
Binary files a/docs/master/.doctrees/advanced/plpgsql.doctree and
b/docs/master/.doctrees/advanced/plpgsql.doctree differ
diff --git a/docs/master/.doctrees/advanced/prepared_statements.doctree
b/docs/master/.doctrees/advanced/prepared_statements.doctree
index db2669f..036ba1e 100644
Binary files a/docs/master/.doctrees/advanced/prepared_statements.doctree and
b/docs/master/.doctrees/advanced/prepared_statements.doctree differ
diff --git a/docs/master/.doctrees/advanced/sql_in_cypher.doctree
b/docs/master/.doctrees/advanced/sql_in_cypher.doctree
index 07bc1a2..c934a78 100644
Binary files a/docs/master/.doctrees/advanced/sql_in_cypher.doctree and
b/docs/master/.doctrees/advanced/sql_in_cypher.doctree differ
diff --git a/docs/master/.doctrees/clauses/create.doctree
b/docs/master/.doctrees/clauses/create.doctree
index b62a99a..6b67d74 100644
Binary files a/docs/master/.doctrees/clauses/create.doctree and
b/docs/master/.doctrees/clauses/create.doctree differ
diff --git a/docs/master/.doctrees/clauses/delete.doctree
b/docs/master/.doctrees/clauses/delete.doctree
index cd438f6..b1df630 100644
Binary files a/docs/master/.doctrees/clauses/delete.doctree and
b/docs/master/.doctrees/clauses/delete.doctree differ
diff --git a/docs/master/.doctrees/clauses/limit.doctree
b/docs/master/.doctrees/clauses/limit.doctree
index 2706bc4..6a37066 100644
Binary files a/docs/master/.doctrees/clauses/limit.doctree and
b/docs/master/.doctrees/clauses/limit.doctree differ
diff --git a/docs/master/.doctrees/clauses/match.doctree
b/docs/master/.doctrees/clauses/match.doctree
index c38102c..331e976 100644
Binary files a/docs/master/.doctrees/clauses/match.doctree and
b/docs/master/.doctrees/clauses/match.doctree differ
diff --git a/docs/master/.doctrees/clauses/order_by.doctree
b/docs/master/.doctrees/clauses/order_by.doctree
index 158fa4c..a9023a5 100644
Binary files a/docs/master/.doctrees/clauses/order_by.doctree and
b/docs/master/.doctrees/clauses/order_by.doctree differ
diff --git a/docs/master/.doctrees/clauses/remove.doctree
b/docs/master/.doctrees/clauses/remove.doctree
index a8968f2..02b2ba1 100644
Binary files a/docs/master/.doctrees/clauses/remove.doctree and
b/docs/master/.doctrees/clauses/remove.doctree differ
diff --git a/docs/master/.doctrees/clauses/return.doctree
b/docs/master/.doctrees/clauses/return.doctree
index 2d9697e..580ee34 100644
Binary files a/docs/master/.doctrees/clauses/return.doctree and
b/docs/master/.doctrees/clauses/return.doctree differ
diff --git a/docs/master/.doctrees/clauses/set.doctree
b/docs/master/.doctrees/clauses/set.doctree
index d056806..a6e1c9b 100644
Binary files a/docs/master/.doctrees/clauses/set.doctree and
b/docs/master/.doctrees/clauses/set.doctree differ
diff --git a/docs/master/.doctrees/clauses/skip.doctree
b/docs/master/.doctrees/clauses/skip.doctree
index 11e5b7c..9db1acd 100644
Binary files a/docs/master/.doctrees/clauses/skip.doctree and
b/docs/master/.doctrees/clauses/skip.doctree differ
diff --git a/docs/master/.doctrees/clauses/with.doctree
b/docs/master/.doctrees/clauses/with.doctree
index 0aa65c2..86f3ad2 100644
Binary files a/docs/master/.doctrees/clauses/with.doctree and
b/docs/master/.doctrees/clauses/with.doctree differ
diff --git a/docs/master/.doctrees/environment.pickle
b/docs/master/.doctrees/environment.pickle
index b401ea1..3aa5eab 100644
Binary files a/docs/master/.doctrees/environment.pickle and
b/docs/master/.doctrees/environment.pickle differ
diff --git a/docs/master/.doctrees/functions/aggregate_functions.doctree
b/docs/master/.doctrees/functions/aggregate_functions.doctree
index 71d3c05..82ca3e5 100644
Binary files a/docs/master/.doctrees/functions/aggregate_functions.doctree and
b/docs/master/.doctrees/functions/aggregate_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/list_functions.doctree
b/docs/master/.doctrees/functions/list_functions.doctree
index 6eea7e4..b3ffad6 100644
Binary files a/docs/master/.doctrees/functions/list_functions.doctree and
b/docs/master/.doctrees/functions/list_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/logarithmic_functions.doctree
b/docs/master/.doctrees/functions/logarithmic_functions.doctree
index c28f0d8..f7027cd 100644
Binary files a/docs/master/.doctrees/functions/logarithmic_functions.doctree
and b/docs/master/.doctrees/functions/logarithmic_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/numeric_functions.doctree
b/docs/master/.doctrees/functions/numeric_functions.doctree
index 84db0b7..a49fad5 100644
Binary files a/docs/master/.doctrees/functions/numeric_functions.doctree and
b/docs/master/.doctrees/functions/numeric_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/predicate_functions.doctree
b/docs/master/.doctrees/functions/predicate_functions.doctree
index cfdbd06..1626d9f 100644
Binary files a/docs/master/.doctrees/functions/predicate_functions.doctree and
b/docs/master/.doctrees/functions/predicate_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/scalar_functions.doctree
b/docs/master/.doctrees/functions/scalar_functions.doctree
index d708290..1db28c7 100644
Binary files a/docs/master/.doctrees/functions/scalar_functions.doctree and
b/docs/master/.doctrees/functions/scalar_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/string_functions.doctree
b/docs/master/.doctrees/functions/string_functions.doctree
index 5fdd2eb..1d86883 100644
Binary files a/docs/master/.doctrees/functions/string_functions.doctree and
b/docs/master/.doctrees/functions/string_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/trigonometric_functions.doctree
b/docs/master/.doctrees/functions/trigonometric_functions.doctree
index 6a16340..586cfb1 100644
Binary files a/docs/master/.doctrees/functions/trigonometric_functions.doctree
and b/docs/master/.doctrees/functions/trigonometric_functions.doctree differ
diff --git a/docs/master/.doctrees/functions/user_functions.doctree
b/docs/master/.doctrees/functions/user_functions.doctree
index 6db055b..3e959eb 100644
Binary files a/docs/master/.doctrees/functions/user_functions.doctree and
b/docs/master/.doctrees/functions/user_functions.doctree differ
diff --git a/docs/master/.doctrees/index.doctree
b/docs/master/.doctrees/index.doctree
index d810e35..156e755 100644
Binary files a/docs/master/.doctrees/index.doctree and
b/docs/master/.doctrees/index.doctree differ
diff --git a/docs/master/.doctrees/intro/aggregation.doctree
b/docs/master/.doctrees/intro/aggregation.doctree
index 66a46ca..0f095b8 100644
Binary files a/docs/master/.doctrees/intro/aggregation.doctree and
b/docs/master/.doctrees/intro/aggregation.doctree differ
diff --git a/docs/master/.doctrees/intro/comparability.doctree
b/docs/master/.doctrees/intro/comparability.doctree
index f32602e..d70ce8d 100644
Binary files a/docs/master/.doctrees/intro/comparability.doctree and
b/docs/master/.doctrees/intro/comparability.doctree differ
diff --git a/docs/master/.doctrees/intro/cypher.doctree
b/docs/master/.doctrees/intro/cypher.doctree
index 36c72bd..680f292 100644
Binary files a/docs/master/.doctrees/intro/cypher.doctree and
b/docs/master/.doctrees/intro/cypher.doctree differ
diff --git a/docs/master/.doctrees/intro/graphs.doctree
b/docs/master/.doctrees/intro/graphs.doctree
index d032aa1..74b4ac3 100644
Binary files a/docs/master/.doctrees/intro/graphs.doctree and
b/docs/master/.doctrees/intro/graphs.doctree differ
diff --git a/docs/master/.doctrees/intro/overview.doctree
b/docs/master/.doctrees/intro/overview.doctree
index bc1e924..45a8622 100644
Binary files a/docs/master/.doctrees/intro/overview.doctree and
b/docs/master/.doctrees/intro/overview.doctree differ
diff --git a/docs/master/.doctrees/intro/precedence.doctree
b/docs/master/.doctrees/intro/precedence.doctree
index af816ea..3f4330a 100644
Binary files a/docs/master/.doctrees/intro/precedence.doctree and
b/docs/master/.doctrees/intro/precedence.doctree differ
diff --git a/docs/master/.doctrees/intro/setup.doctree
b/docs/master/.doctrees/intro/setup.doctree
index d92b96d..f603a18 100644
Binary files a/docs/master/.doctrees/intro/setup.doctree and
b/docs/master/.doctrees/intro/setup.doctree differ
diff --git a/docs/master/.doctrees/intro/types.doctree
b/docs/master/.doctrees/intro/types.doctree
index 4e9a3cb..d8d7593 100644
Binary files a/docs/master/.doctrees/intro/types.doctree and
b/docs/master/.doctrees/intro/types.doctree differ
diff --git a/docs/master/_sources/functions/aggregate_functions.md.txt
b/docs/master/_sources/functions/aggregate_functions.md.txt
index d08f0cf..2c6bdd0 100644
--- a/docs/master/_sources/functions/aggregate_functions.md.txt
+++ b/docs/master/_sources/functions/aggregate_functions.md.txt
@@ -1,6 +1,27 @@
# Aggregation Functions
-<a href="../scripts/functions/aggregation_setup.sql">Data Setup Script</a>
+Functions that activate [auto aggregation](../intro/aggregation.html#).
+
+## Data Setup
+```
+LOAD 'age';
+SET search_path TO ag_catalog;
+
+SELECT create_graph('graph_name');
+
+SELECT * FROM cypher('graph_name', $$
+ CREATE (a:Person {name: 'A', age: 13}),
+ (b:Person {name: 'B', age: 33, eyes: "blue"}),
+ (c:Person {name: 'C', age: 44, eyes: "blue"}),
+ (d1:Person {name: 'D', eyes: "brown"}),
+ (d2:Person {name: 'D'}),
+ (a)-[:KNOWS]->(b),
+ (a)-[:KNOWS]->(c),
+ (a)-[:KNOWS]->(d1),
+ (b)-[:KNOWS]->(d2),
+ (c)-[:KNOWS]->(d2)
+$$) as (a agtype);
+```
## min()
diff --git a/docs/master/_sources/intro/aggregation.md.txt
b/docs/master/_sources/intro/aggregation.md.txt
index 2c2d80d..d49c8f1 100644
--- a/docs/master/_sources/intro/aggregation.md.txt
+++ b/docs/master/_sources/intro/aggregation.md.txt
@@ -1,13 +1,309 @@
# Aggregation
-Generally an aggregation aggr(expr) processes all matching rows for each
aggregation key found in an incoming record (keys are compared using
equivalence).
-For a fixed aggregation key and each matching record, expr is evaluated to a
value. This yields a listof candidate values. Generally the order of
candidate values is unspecified. If the aggregation happens in a
projection with an associated ORDER BY subclause, the list of
candidate values isordered in the same way as the underlying records
and as specified by the associated ORDER BY subclause.
+## Introduction
+
+Generally an aggregation aggr(expr) processes all matching rows for each
aggregation key found in an incoming record (keys are compared using
[equivalence](./comparability.html#)).
+
+In a regular aggregation (i.e. of the form aggr(expr)), the list of aggregated
values is the list of candidate values with all null values removed from it.
+
+## Data Setup
+
+```
+SELECT * FROM cypher('graph_name', $$
+ CREATE (a:Person {name: 'A', age: 13}),
+ (b:Person {name: 'B', age: 33, eyes: "blue"}),
+ (c:Person {name: 'C', age: 44, eyes: "blue"}),
+ (d1:Person {name: 'D', eyes: "brown"}),
+ (d2:Person {name: 'D'}),
+ (a)-[:KNOWS]->(b),
+ (a)-[:KNOWS]->(c),
+ (a)-[:KNOWS]->(d1),
+ (b)-[:KNOWS]->(d2),
+ (c)-[:KNOWS]->(d2)
+$$) as (a agtype);
+```
+
+## Auto Group By
+To calculate aggregated data, Cypher offers aggregation, analogous to SQL’s
GROUP BY.
+
+Aggregating functions take a set of values and calculate An aggregated value
over them. Examples are [avg()](../functions/aggregate_functions.html#avg) that
calculates the average of multiple numeric values, or
[min()](../functions/aggregate_functions.html#min) that finds the smallest
numeric or string value in a set of values. When we say below that an
aggregating function operates on a set of values, we mean these to be the
result of the application of the inner expression(such as n.a [...]
+
+Aggregation can be computed over all the matching subgraphs, or it can be
further divided by introducing grouping keys. These are non-aggregate
expressions, that are used to group the valuesgoing into the aggregate
functions.
+
+Assume we have the following return statement:
+```
+SELECT * FROM cypher('graph_name', $$
+ MATCH (v:Person)
+ RETURN v.name, count(*)
+$$) as (grouping_key agtype, count agtype);
+```
+
+<table>
+ <tr>
+ <td>count</td>
+ <td>key</td>
+ </tr>
+ <tr>
+ <td>"A"</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>"B"</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>"C"</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>"D"</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td colspan="2">1 row</td>
+ </tr>
+</table>
+
+
+We have two return expressions: grouping_key, and count(*). The first,
grouping_key, is not an aggregate function, and so it will be the grouping
key. The latter, count(*) is an aggregate expression. The matching subgraphs
will be divided into different buckets, depending on the grouping key. The
aggregate function will then be run on these buckets, calculating an aggregate
value per bucket.
+
+## Sorting on aggregate functions
+
+To use aggregations to sort the result set, the aggregation must be included
in the RETURN to be used in the ORDER BY.
+
+```
+SELECT *
+FROM cypher('graph_name', $$
+ MATCH (me:Person)-[]->(friend:Person)
+ RETURN count(friend), me
+ ORDER BY count(friend)
+$$) as (friends agtype, me agtype);
+```
+
+## Distinct aggregation
+In a distinct aggregation (i.e. of the form aggr(DISTINCT expr)), the list of
aggregated values is the list of candidate values with all null values removed
from it. Furthermore, in a distinct aggregation, only one of all equivalent
candidate values is included in the list of aggregated values, i.e. duplicates
under equivalence are removed.
+
+
+The DISTINCT operator works in conjunction with aggregation. It is used to
make all values unique before running them through an aggregate function.
+
+```
+SELECT *
+FROM cypher('graph_name', $$
+ MATCH (v:Person)
+ RETURN count(DISTINCT v.eyes), count(v.eyes)
+$$) as (distinct_eyes agtype, eyes agtype);
+```
+
+<table>
+ <tr>
+ <td>distinct_eyes</td>
+ <td>eyes</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td>3</td>
+ </tr>
+ <tr>
+ <td colspan="2">1 row</td>
+ </tr>
+</table>
+
+## Ambiguous Grouping Statements
+
+This feature of not requiring the user to specifiy their grouping keys for a
query allows for ambiguity on what Cypher should qualify as their grouping
keys. For more details [click
here.](https://opencypher.org/articles/2017/07/27/ocig1-aggregations-article/)
+
+Data Setup
+```
+SELECT * FROM cypher('graph_name', $$
+CREATE (:L {a: 1, b: 2, c: 3}),
+ (:L {a: 2, b: 3, c: 1}),
+ (:L {a: 3, b: 1, c: 2})
+$$) as (a agtype);
+```
+
+### Invalid Query in AGE
+AGE's solution to this problem is to not allow a WITH or RETURN column to
combine aggregate functions with variables that are not explicitly listed in
another column of the same WITH or RETURN clause.
+
+
+
+Query:
+```
+SELECT * FROM cypher('graph_name', $$
+ MATCH (x:L)
+ RETURN x.a + count(*) + x.b + count(*) + x.c
+$$) as (a agtype);
+```
+
+Result:
+```
+ERROR: "x" must be either part of an explicitly listed key or used inside an
aggregate function
+LINE 3: RETURN x.a + count(*) + x.b + count(*) + x.c
+```
+
+
+### Valid Query in AGE
+Columns that do not include an aggregate function in AGE are considered to be
the grouping keys for that WITH or RETURN clause.
+
+For the above query, the user could rewrite the query is several ways that
will return results
+
+Query:
+```
+SELECT * FROM cypher('graph_name', $$
+ MATCH (x:L)
+ RETURN (x.a + x.b + x.c) + count(*) + count(*), x.a + x.b + x.c
+$$) as (count agtype, key agtype);
+```
+
+x.a + x.b + x.c is the grouping key. Grouping keys created like this must
include parenthesis.
+
+Results
+<table>
+ <tr>
+ <td>count</td>
+ <td>key</td>
+ </tr>
+ <tr>
+ <td>12</td>
+ <td>6</td>
+ </tr>
+ <tr>
+ <td colspan="2">1 row</td>
+ </tr>
+</table>
+
+
+
+Query
+```
+SELECT * FROM cypher('graph_name', $$
+ MATCH (x:L)
+ RETURN x.a + count(*) + x.b + count(*) + x.c, x.a, x.b, x.c
+$$) as (count agtype, a agtype, b agtype, c agtype);
+```
+
+x.a, x.b, and x.c will be considered different grouping keys
+
+Results:
+
+<table>
+ <thead>
+ <tr>
+ <td>count</td>
+ </td>a<td>
+ </td>b<td>
+ </td>c<td>
+ </tr>
+ </thead>
+ <tr>
+ <td>8</td>
+ <td>3</td>
+ <td>1</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>2</td>
+ <td>3</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>1</td>
+ <td>2</td>
+ <td>3</td>
+ </tr>
+ <tr>
+ <td colspan="4">3 rows</td>
+ </tr>
+</table>
+
+### Vertices and edges in ambiguous grouping
+
+Alternatively, the grouping key can be a vertex or edge, and then any
properties of the vertex or edge can be specified without being explicitly
stated in a WITH or RETURN column.
+
+```
+SELECT * FROM cypher('graph_name', $$
+ MATCH (x:L)
+ RETURN count(*) + count(*) + x.a + x.b + x.c, x
+$$) as (count agtype, key agtype);
+```
+
+Results will be grouped on x, because it is safe to assume that properties be
considered unecessary for grouping to be unambiguous.
+
+Results
+<table>
+ <thead>
+ <tr>
+ <td>count</td>
+ </td>key<td>
+ </tr>
+ </thead>
+ <tr>
+ <td>8</td>
+ <td>{"id": 1407374883553283, "label": "L", "properties": {"a": 3, "b": 1,
"c": 2}}::vertex</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>{"id": 1407374883553281, "label": "L", "properties": {"a": 1, "b": 2,
"c": 3}}::vertex</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>{"id": 1407374883553282, "label": "L", "properties": {"a": 2, "b": 3,
"c": 1}}::vertex</td>
+ </tr>
+ <tr>
+ <td colspan="4">3 rows</td>
+ </tr>
+</table>
+
+
+### Hiding unwanted grouping keys
+
+If the grouping key is considered unecessary for the query output, the
aggregation can be done in a WITH clause then passing information to the RETURN
clause.
+
+SELECT * FROM cypher('graph_name', $$
+ MATCH (x:L)
+ WITH count(*) + count(*) + x.a + x.b + x.c as column, x
+ RETURN column
+$$) as (a agtype);
+
+Results
+<table>
+ <thead>
+ <tr>
+ <td>a</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td colspan="1">3 rows</td>
+ </tr>
+</table>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-In a regular aggregation (i.e. of the form aggr(expr)), the list of
aggregated values is the list of candidate values with all null values
removed from it.In a distinct aggregation (i.e. of the form aggr(DISTINCT
expr)), the list of aggregated values is the listof candidate values with
all null values removed from it. Furthermore, in a distinct
aggregation,only one of all equivalent candidate values is included in
the list of aggregated values [...]
-Finally, the remaining aggregated values are processed by the actual
aggregation function. If the list of aggregated values is empty, the
aggregation function returns a default value (null unlessspecified
otherwise below). Aggregating values of different types (like summing
a number and astring) may lead to runtime errors.
-See
-aggregation functions for more details.
diff --git a/docs/master/_static/functions/aggregation_setup.sql
b/docs/master/_static/functions/aggregation_setup.sql
new file mode 100644
index 0000000..4c97da4
--- /dev/null
+++ b/docs/master/_static/functions/aggregation_setup.sql
@@ -0,0 +1,18 @@
+
+LOAD 'age';
+SET search_path TO ag_catalog;
+
+SELECT create_graph('graph_name');
+
+SELECT * FROM cypher('graph_name', $$
+ CREATE (a:Person {name: 'A', age: 13}),
+ (b:Person {name: 'B', age: 33, eyes: "blue"}),
+ (c:Person {name: 'C', age: 44, eyes: "blue"}),
+ (d1:Person {name: 'D', eyes: "brown"}),
+ (d2:Person {name: 'D'}),
+ (a)-[:KNOWS]->(b),
+ (a)-[:KNOWS]->(c),
+ (a)-[:KNOWS]->(d1),
+ (b)-[:KNOWS]->(d2),
+ (c)-[:KNOWS]->(d2)
+$$) as (a agtype);
diff --git a/docs/master/functions/aggregate_functions.html
b/docs/master/functions/aggregate_functions.html
index 4e3a66c..e92cf13 100644
--- a/docs/master/functions/aggregate_functions.html
+++ b/docs/master/functions/aggregate_functions.html
@@ -127,6 +127,7 @@
<li class="toctree-l1"><a class="reference internal"
href="trigonometric_functions.html">Trigonometric Functions</a></li>
<li class="toctree-l1"><a class="reference internal"
href="string_functions.html">String Functions</a></li>
<li class="toctree-l1 current"><a class="current reference internal"
href="#">Aggregation Functions</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="#data-setup">Data
Setup</a></li>
<li class="toctree-l2"><a class="reference internal" href="#min">min()</a><ul>
<li class="toctree-l3"><a class="reference internal"
href="#using-min-with-lists">Using min() with Lists</a></li>
</ul>
@@ -228,7 +229,29 @@
<div class="tex2jax_ignore mathjax_ignore section"
id="aggregation-functions">
<h1>Aggregation Functions<a class="headerlink" href="#aggregation-functions"
title="Permalink to this headline">¶</a></h1>
-<p><a href="../scripts/functions/aggregation_setup.sql">Data Setup
Script</a></p>
+<p>Functions that activate <span class="xref myst">auto aggregation</span>.</p>
+<div class="section" id="data-setup">
+<h2>Data Setup<a class="headerlink" href="#data-setup" title="Permalink to
this headline">¶</a></h2>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>LOAD 'age';
+SET search_path TO ag_catalog;
+
+SELECT create_graph('graph_name');
+
+SELECT * FROM cypher('graph_name', $$
+ CREATE (a:Person {name: 'A', age: 13}),
+ (b:Person {name: 'B', age: 33, eyes: "blue"}),
+ (c:Person {name: 'C', age: 44, eyes: "blue"}),
+ (d1:Person {name: 'D', eyes: "brown"}),
+ (d2:Person {name: 'D'}),
+ (a)-[:KNOWS]->(b),
+ (a)-[:KNOWS]->(c),
+ (a)-[:KNOWS]->(d1),
+ (b)-[:KNOWS]->(d2),
+ (c)-[:KNOWS]->(d2)
+$$) as (a agtype);
+</pre></div>
+</div>
+</div>
<div class="section" id="min">
<h2>min()<a class="headerlink" href="#min" title="Permalink to this
headline">¶</a></h2>
<p>min() returns the minimum value in a set of values.</p>
diff --git a/docs/master/intro/aggregation.html
b/docs/master/intro/aggregation.html
index 35ed6ac..c18bb33 100644
--- a/docs/master/intro/aggregation.html
+++ b/docs/master/intro/aggregation.html
@@ -38,6 +38,8 @@
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
+ <script async="async"
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+ <script>window.MathJax = {"options": {"processHtmlClass":
"tex2jax_process|mathjax_process|math|output_area"}}</script>
<script type="text/javascript" src="../_static/js/theme.js"></script>
@@ -102,7 +104,21 @@
<li class="toctree-l1"><a class="reference internal" href="types.html">Data
Types - An Introduction to agtype</a></li>
<li class="toctree-l1"><a class="reference internal"
href="comparability.html">Comparability, Equality, Orderability and
Equivalence</a></li>
<li class="toctree-l1"><a class="reference internal"
href="precedence.html">Operator Precedence</a></li>
-<li class="toctree-l1 current"><a class="current reference internal"
href="#">Aggregation</a></li>
+<li class="toctree-l1 current"><a class="current reference internal"
href="#">Aggregation</a><ul>
+<li class="toctree-l2"><a class="reference internal"
href="#introduction">Introduction</a></li>
+<li class="toctree-l2"><a class="reference internal" href="#data-setup">Data
Setup</a></li>
+<li class="toctree-l2"><a class="reference internal"
href="#auto-group-by">Auto Group By</a></li>
+<li class="toctree-l2"><a class="reference internal"
href="#sorting-on-aggregate-functions">Sorting on aggregate functions</a></li>
+<li class="toctree-l2"><a class="reference internal"
href="#distinct-aggregation">Distinct aggregation</a></li>
+<li class="toctree-l2"><a class="reference internal"
href="#ambiguous-grouping-statements">Ambiguous Grouping Statements</a><ul>
+<li class="toctree-l3"><a class="reference internal"
href="#invalid-query-in-age">Invalid Query in AGE</a></li>
+<li class="toctree-l3"><a class="reference internal"
href="#valid-query-in-age">Valid Query in AGE</a></li>
+<li class="toctree-l3"><a class="reference internal"
href="#vertices-and-edges-in-ambiguous-grouping">Vertices and edges in
ambiguous grouping</a></li>
+<li class="toctree-l3"><a class="reference internal"
href="#hiding-unwanted-grouping-keys">Hiding unwanted grouping keys</a></li>
+</ul>
+</li>
+</ul>
+</li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Clauses</span></p>
<ul>
@@ -209,12 +225,263 @@
<div class="tex2jax_ignore mathjax_ignore section" id="aggregation">
<h1>Aggregation<a class="headerlink" href="#aggregation" title="Permalink to
this headline">¶</a></h1>
-<p>Generally an aggregation aggr(expr) processes all matching rows for each
aggregation key found in an incoming record (keys are compared using
equivalence).</p>
-<p>For a fixed aggregation key and each matching record, expr is evaluated to
a value. This yields a listof candidate values. Generally the order of
candidate values is unspecified. If the aggregation happens in a
projection with an associated ORDER BY subclause, the list of
candidate values isordered in the same way as the underlying records
and as specified by the associated ORDER BY subclause.</p>
-<p>In a regular aggregation (i.e. of the form aggr(expr)), the list
of aggregated values is the list of candidate values with all null values
removed from it.In a distinct aggregation (i.e. of the form aggr(DISTINCT
expr)), the list of aggregated values is the listof candidate values with
all null values removed from it. Furthermore, in a distinct
aggregation,only one of all equivalent candidate values is included in
the list of aggregated val [...]
-<p>Finally, the remaining aggregated values are processed by the actual
aggregation function. If the list of aggregated values is empty, the
aggregation function returns a default value (null unlessspecified
otherwise below). Aggregating values of different types (like summing
a number and astring) may lead to runtime errors.</p>
-<p>See</p>
-<p>aggregation functions for more details.</p>
+<div class="section" id="introduction">
+<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to
this headline">¶</a></h2>
+<p>Generally an aggregation aggr(expr) processes all matching rows for each
aggregation key found in an incoming record (keys are compared using <span
class="xref myst">equivalence</span>).</p>
+<p>In a regular aggregation (i.e. of the form aggr(expr)), the list of
aggregated values is the list of candidate values with all null values removed
from it.</p>
+</div>
+<div class="section" id="data-setup">
+<h2>Data Setup<a class="headerlink" href="#data-setup" title="Permalink to
this headline">¶</a></h2>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+ CREATE (a:Person {name: 'A', age: 13}),
+ (b:Person {name: 'B', age: 33, eyes: "blue"}),
+ (c:Person {name: 'C', age: 44, eyes: "blue"}),
+ (d1:Person {name: 'D', eyes: "brown"}),
+ (d2:Person {name: 'D'}),
+ (a)-[:KNOWS]->(b),
+ (a)-[:KNOWS]->(c),
+ (a)-[:KNOWS]->(d1),
+ (b)-[:KNOWS]->(d2),
+ (c)-[:KNOWS]->(d2)
+$$) as (a agtype);
+</pre></div>
+</div>
+</div>
+<div class="section" id="auto-group-by">
+<h2>Auto Group By<a class="headerlink" href="#auto-group-by" title="Permalink
to this headline">¶</a></h2>
+<p>To calculate aggregated data, Cypher offers aggregation, analogous to SQL’s
GROUP BY.</p>
+<p>Aggregating functions take a set of values and calculate An aggregated
value over them. Examples are <a class="reference external"
href="../functions/aggregate_functions.html#avg">avg()</a> that calculates the
average of multiple numeric values, or <a class="reference external"
href="../functions/aggregate_functions.html#min">min()</a> that finds the
smallest numeric or string value in a set of values. When we say below that an
aggregating function operates on a set of values, we mea [...]
+<p>Aggregation can be computed over all the matching subgraphs, or it can be
further divided by introducing grouping keys. These are non-aggregate
expressions, that are used to group the valuesgoing into the aggregate
functions.</p>
+<p>Assume we have the following return statement:</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+ MATCH (v:Person)
+ RETURN v.name, count(*)
+$$) as (grouping_key agtype, count agtype);
+</pre></div>
+</div>
+<table>
+ <tr>
+ <td>count</td>
+ <td>key</td>
+ </tr>
+ <tr>
+ <td>"A"</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>"B"</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>"C"</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>"D"</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td colspan="2">1 row</td>
+ </tr>
+</table>
+<p>We have two return expressions: grouping_key, and count(<em>). The first,
grouping_key, is not an aggregate function, and so it will be the grouping
key. The latter, count(</em>) is an aggregate expression. The matching
subgraphs will be divided into different buckets, depending on the grouping
key. The aggregate function will then be run on these buckets, calculating an
aggregate value per bucket.</p>
+</div>
+<div class="section" id="sorting-on-aggregate-functions">
+<h2>Sorting on aggregate functions<a class="headerlink"
href="#sorting-on-aggregate-functions" title="Permalink to this
headline">¶</a></h2>
+<p>To use aggregations to sort the result set, the aggregation must be
included in the RETURN to be used in the ORDER BY.</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT *
+FROM cypher('graph_name', $$
+ MATCH (me:Person)-[]->(friend:Person)
+ RETURN count(friend), me
+ ORDER BY count(friend)
+$$) as (friends agtype, me agtype);
+</pre></div>
+</div>
+</div>
+<div class="section" id="distinct-aggregation">
+<h2>Distinct aggregation<a class="headerlink" href="#distinct-aggregation"
title="Permalink to this headline">¶</a></h2>
+<p>In a distinct aggregation (i.e. of the form aggr(DISTINCT expr)), the list
of aggregated values is the list of candidate values with all null values
removed from it. Furthermore, in a distinct aggregation, only one of all
equivalent candidate values is included in the list of aggregated values, i.e.
duplicates under equivalence are removed.</p>
+<p>The DISTINCT operator works in conjunction with aggregation. It is used to
make all values unique before running them through an aggregate function.</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT *
+FROM cypher('graph_name', $$
+ MATCH (v:Person)
+ RETURN count(DISTINCT v.eyes), count(v.eyes)
+$$) as (distinct_eyes agtype, eyes agtype);
+</pre></div>
+</div>
+<table>
+ <tr>
+ <td>distinct_eyes</td>
+ <td>eyes</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td>3</td>
+ </tr>
+ <tr>
+ <td colspan="2">1 row</td>
+ </tr>
+</table>
+</div>
+<div class="section" id="ambiguous-grouping-statements">
+<h2>Ambiguous Grouping Statements<a class="headerlink"
href="#ambiguous-grouping-statements" title="Permalink to this
headline">¶</a></h2>
+<p>This feature of not requiring the user to specifiy their grouping keys for
a query allows for ambiguity on what Cypher should qualify as their grouping
keys. For more details <a class="reference external"
href="https://opencypher.org/articles/2017/07/27/ocig1-aggregations-article/">click
here.</a></p>
+<p>Data Setup</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+CREATE (:L {a: 1, b: 2, c: 3}),
+ (:L {a: 2, b: 3, c: 1}),
+ (:L {a: 3, b: 1, c: 2})
+$$) as (a agtype);
+</pre></div>
+</div>
+<div class="section" id="invalid-query-in-age">
+<h3>Invalid Query in AGE<a class="headerlink" href="#invalid-query-in-age"
title="Permalink to this headline">¶</a></h3>
+<p>AGE’s solution to this problem is to not allow a WITH or RETURN column to
combine aggregate functions with variables that are not explicitly listed in
another column of the same WITH or RETURN clause.</p>
+<p>Query:</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+ MATCH (x:L)
+ RETURN x.a + count(*) + x.b + count(*) + x.c
+$$) as (a agtype);
+</pre></div>
+</div>
+<p>Result:</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span><span class="n">ERROR</span><span
class="p">:</span> <span class="s2">"x"</span> <span
class="n">must</span> <span class="n">be</span> <span class="n">either</span>
<span class="n">part</span> <span class="n">of</span> <span class="n">an</span>
<span class="n">explicitly</span> <span class="n">listed</span> <span
class="n">key</span> <span class="ow">or</span> <span class="n">used</span>
<span [...]
+<span class="n">LINE</span> <span class="mi">3</span><span class="p">:</span>
<span class="n">RETURN</span> <span class="n">x</span><span
class="o">.</span><span class="n">a</span> <span class="o">+</span> <span
class="n">count</span><span class="p">(</span><span class="o">*</span><span
class="p">)</span> <span class="o">+</span> <span class="n">x</span><span
class="o">.</span><span class="n">b</span> <span class="o">+</span> <span
class="n">count</span><span class="p">(</span><span clas [...]
+</pre></div>
+</div>
+</div>
+<div class="section" id="valid-query-in-age">
+<h3>Valid Query in AGE<a class="headerlink" href="#valid-query-in-age"
title="Permalink to this headline">¶</a></h3>
+<p>Columns that do not include an aggregate function in AGE are considered to
be the grouping keys for that WITH or RETURN clause.</p>
+<p>For the above query, the user could rewrite the query is several ways that
will return results</p>
+<p>Query:</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+ MATCH (x:L)
+ RETURN (x.a + x.b + x.c) + count(*) + count(*), x.a + x.b + x.c
+$$) as (count agtype, key agtype);
+</pre></div>
+</div>
+<p>x.a + x.b + x.c is the grouping key. Grouping keys created like this must
include parenthesis.</p>
+<p>Results</p>
+<table>
+ <tr>
+ <td>count</td>
+ <td>key</td>
+ </tr>
+ <tr>
+ <td>12</td>
+ <td>6</td>
+ </tr>
+ <tr>
+ <td colspan="2">1 row</td>
+ </tr>
+</table>
+<p>Query</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+ MATCH (x:L)
+ RETURN x.a + count(*) + x.b + count(*) + x.c, x.a, x.b, x.c
+$$) as (count agtype, a agtype, b agtype, c agtype);
+</pre></div>
+</div>
+<p>x.a, x.b, and x.c will be considered different grouping keys</p>
+<p>Results:</p>
+<table>
+ <thead>
+ <tr>
+ <td>count</td>
+ </td>a<td>
+ </td>b<td>
+ </td>c<td>
+ </tr>
+ </thead>
+ <tr>
+ <td>8</td>
+ <td>3</td>
+ <td>1</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>2</td>
+ <td>3</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>1</td>
+ <td>2</td>
+ <td>3</td>
+ </tr>
+ <tr>
+ <td colspan="4">3 rows</td>
+ </tr>
+</table>
+</div>
+<div class="section" id="vertices-and-edges-in-ambiguous-grouping">
+<h3>Vertices and edges in ambiguous grouping<a class="headerlink"
href="#vertices-and-edges-in-ambiguous-grouping" title="Permalink to this
headline">¶</a></h3>
+<p>Alternatively, the grouping key can be a vertex or edge, and then any
properties of the vertex or edge can be specified without being explicitly
stated in a WITH or RETURN column.</p>
+<div class="highlight-default notranslate"><div
class="highlight"><pre><span></span>SELECT * FROM cypher('graph_name',
$$
+ MATCH (x:L)
+ RETURN count(*) + count(*) + x.a + x.b + x.c, x
+$$) as (count agtype, key agtype);
+</pre></div>
+</div>
+<p>Results will be grouped on x, because it is safe to assume that properties
be considered unecessary for grouping to be unambiguous.</p>
+<p>Results</p>
+<table>
+ <thead>
+ <tr>
+ <td>count</td>
+ </td>key<td>
+ </tr>
+ </thead>
+ <tr>
+ <td>8</td>
+ <td>{"id": 1407374883553283, "label": "L", "properties": {"a": 3, "b": 1,
"c": 2}}::vertex</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>{"id": 1407374883553281, "label": "L", "properties": {"a": 1, "b": 2,
"c": 3}}::vertex</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>{"id": 1407374883553282, "label": "L", "properties": {"a": 2, "b": 3,
"c": 1}}::vertex</td>
+ </tr>
+ <tr>
+ <td colspan="4">3 rows</td>
+ </tr>
+</table>
+</div>
+<div class="section" id="hiding-unwanted-grouping-keys">
+<h3>Hiding unwanted grouping keys<a class="headerlink"
href="#hiding-unwanted-grouping-keys" title="Permalink to this
headline">¶</a></h3>
+<p>If the grouping key is considered unecessary for the query output, the
aggregation can be done in a WITH clause then passing information to the RETURN
clause.</p>
+<p>SELECT * FROM cypher(‘graph_name’, $<span class="math notranslate
nohighlight">\(
+ MATCH (x:L)
+ WITH count(*) + count(*) + x.a + x.b + x.c as column, x
+ RETURN column
+\)</span>$) as (a agtype);</p>
+<p>Results</p>
+<table>
+ <thead>
+ <tr>
+ <td>a</td>
+ </tr>
+ </thead>
+ <tr>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ </tr>
+ <tr>
+ <td colspan="1">3 rows</td>
+ </tr>
+</table>
+</div>
+</div>
</div>
diff --git a/docs/master/searchindex.js b/docs/master/searchindex.js
index 80933c2..96fecc5 100644
--- a/docs/master/searchindex.js
+++ b/docs/master/searchindex.js
@@ -1 +1 @@
-Search.setIndex({docnames:["advanced/advanced","advanced/advanced_overview","advanced/plpgsql","advanced/prepared_statements","advanced/sql_in_cypher","clauses/create","clauses/delete","clauses/limit","clauses/match","clauses/order_by","clauses/remove","clauses/return","clauses/set","clauses/skip","clauses/with","functions/aggregate_functions","functions/list_functions","functions/logarithmic_functions","functions/numeric_functions","functions/predicate_functions","functions/scalar_funct
[...]
\ No newline at end of file
+Search.setIndex({docnames:["advanced/advanced","advanced/advanced_overview","advanced/plpgsql","advanced/prepared_statements","advanced/sql_in_cypher","clauses/create","clauses/delete","clauses/limit","clauses/match","clauses/order_by","clauses/remove","clauses/return","clauses/set","clauses/skip","clauses/with","functions/aggregate_functions","functions/list_functions","functions/logarithmic_functions","functions/numeric_functions","functions/predicate_functions","functions/scalar_funct
[...]
\ No newline at end of file