GROUP BY and HAVING
When a result contains aggregates without an explicit GROUP BY, nonaggregate projected expressions that refer to input values become grouping keys. A property the matched elements do not store is still one of those values: it is null on every row, and an empty match produces no group. A written constant is not a key, so RETURN 7, COUNT(*) on an empty match stays one row. GROUP BY () forces that single global group even for a missing property.
MATCH (p:Person)OPTIONAL MATCH (p)-[:Knows]->(friend)RETURN p.name AS name, COUNT(friend) AS friendsGROUP BY name ORDER BY name;This returns Alice: 1, Bob: 1 and Cara: 0. COUNT(friend) ignores the null optional binding.
Explicit GROUP BY accepts binding variables, including output aliases. Grouping an element groups its identity while retaining the columns needed for property access. GROUP BY () chooses one global group.
A property used as a group key, including an implicit key next to an aggregate, must use one comparable family. Integers and floats stay one family. Boolean, string, and byte-string values do not. Mixing those families is an invalid query, rather than grouping the string form of each cell. A fragment that does not store the property contributes null and does not add a family.
SELECT COUNT(*) AS people FROM social MATCH (p:Person)GROUP BY () HAVING COUNT(*) > 0;SELECT HAVING filters completed groups. Ungrouped input references and nested aggregate calls are rejected. An empty global aggregate still returns one row: COUNT is 0, COLLECT_LIST is an empty list, and numeric aggregates are null.
Arithmetic and concatenation in HAVING use each stored fragment type. An incompatible operation produces null before IS UNKNOWN or other enclosing wrappers are evaluated. Stored helper columns remain dependent on the original group bindings.