Neo4j Cypher查询含rating变量结果异常原因咨询
问题根源:Cypher的自动分组规则导致结果偏差
核心问题出在Cypher对聚合函数与非聚合变量的分组逻辑:当WITH或RETURN子句中同时存在聚合函数(如avg())和未被聚合的变量时,Cypher会自动将所有非聚合变量作为分组依据,把值相同的行归为一组后再计算聚合结果。
错误查询的问题所在
看你第一个出错的查询:
match (p:Person{name: 'Tom Hanks'})-[:ACTED_IN]->(m:Movie)<-[r:RATED]-(u:User) with avg(r.rating) as average, r.rating as rating, m.title as movie return movie, average, rating order by average desc limit 1
这里WITH里同时有avg(r.rating)、r.rating和m.title。Cypher会按r.rating + m.title分组——也就是每一条电影的评分记录单独成组(每条记录的r.rating大概率不同)。此时avg(r.rating)计算的是单条评分的平均值(也就是评分本身),所以你得到的5.0只是《Catch Me If You Can》里某一个用户的满分评分,而非这部电影的整体用户平均分。
你第三次尝试的查询同理:
match (p:Person{name: 'Tom Hanks'})-[:ACTED_IN]->(m:Movie)<-[r:RATED]-(u:User) with r.rating as rating, m.title as movie return movie, avg(rating) as average, rating order by average desc limit 1
RETURN中avg(rating)与movie、rating共存,分组依据还是movie + rating,avg(rating)依然是单条评分的值,结果自然错误。
正确查询的逻辑
而正确的查询:
match (p:Person{name: 'Tom Hanks'})-[:ACTED_IN]->(m:Movie)<-[r:RATED]-(u:User) with avg(r.rating) as average, m.title as movie return movie, average order by average desc limit 1
这里WITH里只有avg(r.rating)和m.title,Cypher会按m.title(即电影标题)分组,把同一部电影的所有评分记录归为一组,再计算该组的平均评分,得到的才是每部电影的真实用户平均分,排序后取最高值就是正确结果。
延伸:同时获取平均分和单条评分
如果需要同时返回电影的平均分和对应的单条评分,得先算出电影的平均分,再关联原评分数据,比如:
match (p:Person{name: 'Tom Hanks'})-[:ACTED_IN]->(m:Movie)<-[r:RATED]-(u:User) with m, avg(r.rating) as movie_avg match (m)<-[r:RATED]-(u:User) return m.title as movie, movie_avg, r.rating as rating order by movie_avg desc, rating desc limit 1
这样既保留了电影的真实平均分,又能关联到对应的评分记录。
内容的提问来源于stack exchange,提问作者Vincenzo
相关产品推荐
相关产品推荐

