我从neo4j密码聚合类https://www.youtube.com/watch?v=wfMTg0ujVjk复制了一个示例类查询
Match (a:Actor)
Where a.born is not null
And a.name starts with 'Tom'
with count(a) as NumActors, collect(duration.between(date(a.born), date())) as Ages
Unwind Ages AS x
Return sum(x), sum(x)/NumActors
但是,在类提供的neo4j Web控制台中,我得到了这个错误
Aggregation column contains implicit grouping expressions. For example, in 'RETURN n.a, n.a + n.b + count(*)' the aggregation expression 'n.a + n.b + count(*)' includes the implicit grouping key 'n.b'. It may be possible to rewrite the query by extracting these grouping/aggregation expressions into a preceding WITH clause. Illegal expression(s): NumActors (line 6, column 8 (offset: 183))
"Return sum(x), sum(x)/NumActors"
^
显然,此查询有效
Match (a:Actor)
Where a.born is not null
And a.name starts with 'Tom'
with count(a) as NumActors, collect(duration.between(date(a.born), date())) as Ages
Unwind Ages AS x
Return sum(x)
因此,当我们使用NumActors作为隐式聚合键sum(x)时,它会抱怨。我如何通过更新查询(计算sum和average)来实现相同的目标?我的初始查询语法看起来非常好...
3条答案
按热度按时间btxsgosb1#
为此,请使用函数AVG():
样品结果:
参考:https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-avg-duration
为了解释您的错误,neo4j允许聚合表达式,如果它符合此准则中所述的一些要求:https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#grouping-keys
如果你坚持使用你的原始查询,这是neo4j错误信息中所述的修复方法。你应该先使用WITH来获取sum(),然后用它来计算平均值。
62o28rlo2#
这是一个有点棘手的问题。所以我会尽可能地简化它。让我们试着理解聚合是如何工作的,对于这个查询:
我们首先匹配名字以
Tom
开头并有出生日期的演员,假设我们有10个演员,在MATCH
和WHERE
子句执行之后。这将执行两个聚合操作,
count
和collect
,但请注意,我们没有专门指定任何分组键。因此,此查询的输出将是一个包含两列NumActors
和Ages
的单行。现在,我们展开age数组,因此现在我们将有10行,最后,我们返回总和。因为没有明确的分组键,所以计算所有数据行的和。2因此它可以工作。让我们考虑一下您的查询:
UNWIND
stage之前的所有内容都与上面相同。现在,请注意return语句:这里也没有指定显式分组键。因此,
sum(x)
将包含所有行,但术语sum(x)/NumActors
是错误的,因为Neo4j
无法确定要从哪一行中选取NumActors
的值,因为它没有被指定为分组键。这就是为什么会出现错误。消息如下:很明显,键
n.b
正在分组,它不能用在聚合表达式中。类似地,这里NumActors
正在分组,我们不能用在聚合表达式中。试试这个:pgky5nke3#
该错误是由于您在
RETURN
子句中使用了NumActors
,但没有使其成为显式分组键而导致的。选项1
指定
NumActors
作为显式分组键:选项2
不要在
RETURN
子句中进行聚合:注意:上面的代码还通过在第一个(现在也是唯一的)
WITH
子句中执行SUM
来简化(并加快)查询,您不需要浪费的COLLECT
-〉UNWIND
-〉SUM
序列。选项3
如果不需要返回所有年龄的总和,直接计算平均年龄即可:
附录
还有一个性能改进可以用于所有的解决方案,它还可以消除一个可能的错误。
我们应该计算一次
DATE()
的值,将其放入一个变量中,然后使用该变量计算所有的年龄,这样不仅可以避免重复调用DATE()
,而且可以保证所有的年龄都使用同一个当前日期计算。如果没有这个调整,那么我们就有可能在计算过程中使用多个当前日期,这将给我们带来不一致的结果。
例如,选项3可以变成这样: