聚合函数
聚合函数对一组值执行计算,并返回单个值。聚合可以在所有匹配路径上进行计算,也可以通过引入分组键 (grouping keys) 进行进一步细分。
| 要了解更多关于 Cypher® 如何处理针对零行数据执行聚合的信息,请访问 Neo4j 知识库 → 理解针对零行数据的聚合。 |
示例图
以下图表用于下方的示例
要重新创建该图,请在空的 Neo4j 数据库中运行以下查询
CREATE
(keanu:Person {name: 'Keanu Reeves', age: 58}),
(liam:Person {name: 'Liam Neeson', age: 70}),
(carrie:Person {name: 'Carrie Anne Moss', age: 55}),
(guy:Person {name: 'Guy Pearce', age: 55}),
(kathryn:Person {name: 'Kathryn Bigelow', age: 71}),
(speed:Movie {title: 'Speed'}),
(keanu)-[:ACTED_IN]->(speed),
(keanu)-[:KNOWS]->(carrie),
(keanu)-[:KNOWS]->(liam),
(keanu)-[:KNOWS]->(kathryn),
(carrie)-[:KNOWS]->(guy),
(liam)-[:KNOWS]->(guy)
avg()
语法 |
|
||
描述 |
返回一组 |
||
参数 |
名称 |
类型 |
描述 |
|
|
聚合以形成平均值的值。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
RETURN avg(p.age)
返回属性 age 中所有值的平均值
| avg(p.age) |
|---|
|
行:1 |
UNWIND [duration('P2DT3H'), duration('PT1H45S')] AS dur
RETURN avg(dur)
返回提供的两个 DURATION 值的平均值
| avg(dur) |
|---|
|
行:1 |
collect()
语法 |
|
||
描述 |
返回一个包含表达式所返回值的列表。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
聚合到一个列表中的值。 |
|
返回 |
|
||
任何 |
|
MATCH (p:Person)
RETURN collect(p.age)
所有值被收集并返回在一个单一的列表中
| collect(p.age) |
|---|
|
行:1 |
collect_list()仅限 Cypher 25在 Neo4j 2026.02 中引入
语法 |
|
||
描述 |
返回一个包含表达式所返回值的列表。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
聚合到一个列表中的值。 |
|
返回 |
|
||
任何 |
|
MATCH (p:Person)
RETURN collect_list(p.age)
所有值被收集并返回在一个单一的列表中
| collect_list(p.age) |
|---|
|
行:1 |
count()
语法 |
|
||
描述 |
返回值的数量或行数。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
返回 |
|
||
|
|
|
Neo4j 维护一个用于存储计数元数据的事务性计数存储,这可以显著提高使用 count() 函数的查询速度。有关计数存储的更多信息,请参阅 Neo4j 知识库 → 使用计数存储进行快速计数。 |
使用 count(*) 返回节点数量
函数 count(*) 可用于返回节点数量;例如,与节点 n 连接的节点数量。
MATCH (p:Person {name: 'Keanu Reeves'})-->(x)
RETURN labels(p), p.age, count(*)
返回起始节点 Keanu Reeves 的标签和 age 属性,以及与它相关的节点数量
| labels(p) | p.age | count(*) |
|---|---|---|
|
|
|
行:1 |
||
使用 count(*) 对关系类型进行分组和计数
函数 count(*) 可用于对匹配的关系类型进行分组,并返回每种类型的数量。
MATCH (p:Person {name: 'Keanu Reeves'})-[r]->()
RETURN type(r), count(*)
对匹配的关系类型进行分组,并返回关系类型的组计数
| type(r) | count(*) |
|---|---|
|
|
|
|
行:2 |
|
计算非 null 值
除了简单地使用 count(*) 返回行数外,函数 count(expression) 还可用于返回表达式所返回的非 null 值的数量。
MATCH (p:Person)
RETURN count(p.age)
返回带有标签 Person 且具有 age 属性的节点数量:(要计算总和,请使用 sum(n.age))
| count(p.age) |
|---|
|
行:1 |
计数的去重与不去重
count 函数的默认行为是统计所有匹配结果,包括重复项。要避免统计重复项,请使用 DISTINCT 关键字。
在聚合函数中使用 ALL 关键字也是可能的。这将统计所有结果(包括重复项),在功能上与不使用 DISTINCT 关键字相同。ALL 关键字是作为 Cypher GQL 一致性的一部分引入的。
此示例试图找到 Keanu Reeves 的所有朋友的朋友并统计他们。它展示了使用 ALL 和 DISTINCT 关键字的行为
MATCH (p:Person)-->(friend:Person)-->(friendOfFriend:Person)
WHERE p.name = 'Keanu Reeves'
RETURN friendOfFriend.name, count(friendOfFriend), count(ALL friendOfFriend), count(DISTINCT friendOfFriend)
节点 Carrie Anne Moss 和 Liam Neeson 都有指向 Guy Pearce 的 KNOWS 出站关系。因此,如果不使用 DISTINCT,Guy Pearce 节点将被统计两次。
| friendOfFriend.name | count(friendOfFriend) | count(ALL friendOfFriend) | count(DISTINCT friendOfFriend) |
|---|---|---|---|
|
|
|
|
行:1 |
|||
max()
语法 |
|
||
描述 |
返回一组值中的最大值。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
返回 |
|
||
计算时会排除任何 |
在混合集合中,任何数值始终被认为高于任何 |
列表按字典顺序进行比较,即从列表开头到结尾对元素进行逐对升序比较。 |
|
UNWIND [1, 'a', null, 0.2, 'b', '1', '99'] AS val
RETURN max(val)
返回混合集合中所有值的最大值——在此例中为数值 1
| max(val) |
|---|
|
行:1 |
|
值 |
UNWIND [[1, 'a', 89], [1, 2]] AS val
RETURN max(val)
返回集合中所有列表的最大值——在此例中为列表 [1, 2],因为数字 2 被认为高于 STRING 'a',即使列表 [1, 'a', 89] 包含更多元素。
| max(val) |
|---|
|
行:1 |
MATCH (p:Person)
RETURN max(p.age)
返回属性 age 中所有值的最大值
| max(p.age) |
|---|
|
行:1 |
min()
语法 |
|
||
描述 |
返回一组值中的最小值。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
返回 |
|
||
计算时会排除任何 |
在混合集合中,任何 |
列表按字典顺序进行比较,即从列表开头到结尾对元素进行逐对升序比较。 |
|
UNWIND [1, 'a', null, 0.2, 'b', '1', '99'] AS val
RETURN min(val)
返回混合集合中所有值的最小值——在此例中为 STRING 值 "1"。请注意,(数值)值 0.2 虽然乍看之下似乎是列表中的最小值,但它被认为高于 "1",因为后者是一个 STRING。
| min(val) |
|---|
|
行:1 |
UNWIND ['d', [1, 2], ['a', 'c', 23]] AS val
RETURN min(val)
返回集合中所有值的最小值——在此例中为列表 ['a', 'c', 23],因为 (i) 这两个列表都被认为低于 STRING "d",且 (ii) STRING "a" 被认为低于数值 1。
| min(val) |
|---|
|
行:1 |
MATCH (p:Person)
RETURN min(p.age)
返回属性 age 中所有值的最小值
| min(p.age) |
|---|
|
行:1 |
percentileCont()
语法 |
|
||
描述 |
使用线性插值法返回一组值中指定百分位数的数值。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
|
|
0.0 到 1.0 之间的百分位数。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
RETURN percentileCont(p.age, 0.4)
返回属性 age 中值的第 40 百分位数,通过加权平均计算得出
| percentileCont(p.age, 0.4) |
|---|
|
行:1 |
percentile_cont()仅限 Cypher 25在 Neo4j 2026.02 中引入
语法 |
|
||
描述 |
使用线性插值法返回一组值中指定百分位数的数值。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
|
|
0.0 到 1.0 之间的百分位数。 |
|
返回 |
|
||
此函数是 percentileCont() 函数的别名,作为 Cypher GQL 一致性的一部分引入。
计算时会排除任何 |
|
MATCH (p:Person)
RETURN percentile_cont(p.age, 0.4)
返回属性 age 中值的第 40 百分位数,通过加权平均计算得出
| percentile_cont(p.age, 0.4) |
|---|
|
行:1 |
percentileDisc()
语法 |
|
||
描述 |
使用舍入法返回一组值中与指定百分位数最接近的 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
|
|
0.0 到 1.0 之间的百分位数。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
RETURN percentileDisc(p.age, 0.5)
返回属性 age 中值的第 50 百分位数
| percentileDisc(p.age, 0.5) |
|---|
|
行:1 |
percentile_disc()仅限 Cypher 25在 Neo4j 2026.02 中引入
语法 |
|
||
描述 |
使用舍入法返回一组值中与指定百分位数最接近的 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
|
|
0.0 到 1.0 之间的百分位数。 |
|
返回 |
|
||
此函数是 percentileDisc() 函数的别名,作为 Cypher GQL 一致性的一部分引入。
计算时会排除任何 |
|
MATCH (p:Person)
RETURN percentile_disc(p.age, 0.5)
返回属性 age 中值的第 50 百分位数
| percentile_disc(p.age, 0.5) |
|---|
|
行:1 |
stDev()
语法 |
|
||
描述 |
返回给定值在样本总体中的标准差。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
用于计算标准差的值。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
WHERE p.name IN ['Keanu Reeves', 'Liam Neeson', 'Carrie Anne Moss']
RETURN stDev(p.age)
返回属性 age 中值的标准差
| stDev(p.age) |
|---|
|
行:1 |
stdev_samp()仅限 Cypher 25在 Neo4j 2026.02 中引入
语法 |
|
||
描述 |
返回给定值在样本总体中的标准差。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
用于计算标准差的值。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
WHERE p.name IN ['Keanu Reeves', 'Liam Neeson', 'Carrie Anne Moss']
RETURN stdev_samp(p.age)
返回属性 age 中值的标准差
| stdev_samp(p.age) |
|---|
|
行:1 |
stDevP()
语法 |
|
||
描述 |
返回给定值在整个总体中的标准差。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
用于计算总体标准差的值。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
WHERE p.name IN ['Keanu Reeves', 'Liam Neeson', 'Carrie Anne Moss']
RETURN stDevP(p.age)
返回属性 age 中值的总体标准差
| stDevP(p.age) |
|---|
|
行:1 |
stdev_pop()仅限 Cypher 25在 Neo4j 2026.02 中引入
语法 |
|
||
描述 |
返回给定值在整个总体中的标准差。 |
||
参数 |
名称 |
类型 |
描述 |
|
|
用于计算总体标准差的值。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
WHERE p.name IN ['Keanu Reeves', 'Liam Neeson', 'Carrie Anne Moss']
RETURN stdev_pop(p.age)
返回属性 age 中值的总体标准差
| stdev_pop(p.age) |
|---|
|
行:1 |
sum()
语法 |
|
||
描述 |
返回一组 |
||
参数 |
名称 |
类型 |
描述 |
|
|
要聚合的值。 |
|
返回 |
|
||
计算时会排除任何 |
|
MATCH (p:Person)
RETURN sum(p.age)
返回属性 age 中所有值的总和
| sum(p.age) |
|---|
|
行:1 |
UNWIND [duration('P2DT3H'), duration('PT1H45S')] AS dur
RETURN sum(dur)
返回提供的两个时长的总和
| sum(dur) |
|---|
|
行:1 |
聚合表达式与分组键
聚合表达式是指包含一个或多个聚合函数的表达式。简单的聚合表达式由单个聚合函数组成。例如,sum(x.a) 是一个仅由聚合函数 sum( ) 构成的聚合表达式,其参数为 x.a。聚合表达式也可以更复杂,其中一个或多个聚合函数的结果作为其他表达式的输入参数。例如,0.1 * (sum(x.a) / count(x.b)) 是一个聚合表达式,它包含两个聚合函数:以 x.a 为参数的 sum( ) 和以 x.b 为参数的 count( )。两者都是除法表达式的输入参数。
分组键是用于对输入到聚合函数中的值进行分组的非聚合表达式。例如,在以下包含两个返回表达式 n 和 count(*) 的查询中:
RETURN n, count(*)
第一个表达式 n 不是聚合函数,因此它将作为分组键。后者 count(*) 是一个聚合函数。匹配的路径将根据分组键被划分为不同的存储桶。然后,聚合函数将在这些存储桶上运行,计算每个存储桶的聚合值。
聚合函数的输入表达式可以包含任何表达式,包括非分组键的表达式。但是,并非所有表达式都能与聚合函数组合。下面的示例将抛出错误,因为 n.x(不是分组键)与聚合函数 count(*) 结合使用了。
RETURN n.x + count(*)
要使用聚合函数对结果集进行排序,聚合必须包含在 RETURN 子句之后的 ORDER BY 子句中。
示例
MATCH (p:Person)
RETURN max(p.age)
| max(p.age) |
|---|
|
行:1 |
MATCH (p:Person)
RETURN max(p.age) + 1
| max(p.age) + 1 |
|---|
|
行:1 |
注意 p 是一个分组键
MATCH (p:Person{name:'Keanu Reeves'})-[:KNOWS]-(f:Person)
RETURN p, p.age - max(f.age)
| p | p.age - max(f.age) |
|---|---|
|
|
行:1 |
|
注意 p.age 是一个分组键
MATCH (p:Person {name:'Keanu Reeves'})-[:KNOWS]-(f:Person)
RETURN p.age, p.age - max(f.age)
| p.age | p.age - max(f.age) |
|---|---|
|
|
行:1 |
|
分组键本身可以是复杂的表达式。为了提高查询的可读性,Cypher 仅在以下情况将聚合表达式中的子表达式识别为分组键:
-
变量 - 例如
RETURN p, p.age - max(f.age)中的p。 -
属性访问 - 例如
RETURN p.age, p.age - max(f.age)中的p.age。 -
Map 访问 - 例如
WITH {name:'Keanu Reeves', age:58} AS p RETURN p.age, p.age - max(p.age)中的p.age。
如果需要将更复杂的分组键作为聚合表达式中的操作数,始终可以使用 WITH 提前对它们进行投影。
使用属性 p.age 会抛出异常,因为 p.age 不是一个分组键。因此,它不能用于包含聚合函数的表达式中。以下两个查询会产生相同的错误消息:
MATCH (p:Person {name:'Keanu Reeves'})-[:KNOWS]-(f:Person)
RETURN p.age - max(f.age)
MATCH (p:Person {name:'Keanu Reeves'})-[:KNOWS]-(f:Person)
RETURN p.age + p.age, p.age + p.age - max(f.age)
42I18: 错误: 语法错误或访问规则违规 - 对隐式分组表达式的引用无效。聚合列包含变量 42001:错误:语法错误或访问规则冲突 - 无效语法 |
然而,如果将后者改写如下,查询即可生效:
MATCH (p:Person {name:'Keanu Reeves'})-[:KNOWS]-(f:Person)
WITH p.age + p.age AS groupingKey, f
RETURN groupingKey, groupingKey - max(f.age)
| groupingKey | groupingKey - max(f.age) |
|---|---|
|
|
行:1 |
|