我有一个遵循这种形式的Neo4j数据库:
主题的一个中心节点。所有当前医疗数据都以当前关系作为单独节点加入其中。如果特定节点包含医学测试分数,并且该主题已经进行了该测试,之后它将加入具有先前关系的分数。
e.g:
(subject)<-[:Current]-(current_medical_score)<-[:Previous*]<-(previous_medical_score)
我要做的是计算此医学测试的平均值,并返回平均值小于确定的截止点的所有主题ID。但是,我的请求似乎只考虑current_medical_score节点执行平均操作时的值。
MATCH (subject)<-[:Current|:Previous*]-(scores)
WHERE scores.MISD IS NOT NULL AND scores.MISD <> 999
WITH scores, avg(scores.MISD) as sumMis
WHERE sumMis < 4
RETURN scores.SID, sumMis;
+---------------------+
| scores.SID | sumMis |
+---------------------+
| "330" | 2.0 |
| "2445" | 2.0 |
+---------------------+
我检查分数MISD是否为空或999,因为一些提供数据的机构利用999来表示缺失数据。对象2445具有当前MIS得分2和一个先前得分为8,因此预期平均值应为5.0
不是2.0
我无法弄清楚通过可变数量关系所需的语法,并计算所有相关节点中值之间的平均值。
非常感谢任何帮助。
答案 0 :(得分:1)
考虑此样本数据集:
create (subject:Subject {ID:"2442"})
<-[:Current]-(:Score {MISD:2.0, SID: "2442"})
<-[:Previous]-(:Score {MISD:8.0, SID: "2442"})
您的问题是您是按score
变量对结果进行分组。您应该按subject
进行分组。这是:WITH subject, (...)
而不是WITH scores, (...)
MATCH (subject:Subject)<-[:Current|:Previous*]-(scores)
WHERE scores.MISD IS NOT NULL AND scores.MISD <> 999
WITH subject, avg(scores.MISD) as sumMis
RETURN subject.ID, sumMis;
输出:
╒════════════╤════════╕
│"subject.ID"│"sumMis"│
╞════════════╪════════╡
│"2442" │5 │
└────────────┴────────┘
答案 1 :(得分:1)
您之所以看到这些结果,是因为:
WITH scores, avg(scores.MISD) as sumMis
聚合函数(如avg()
)仅对非聚合列具有意义,这些列构成了分组键。
在这种情况下,这一行显示:&#34;对于每个单独的分数(因为scores
这里不是分数的集合,它是单个分数,每个记录一个分数/行),找到该单个分数的MISD属性的平均值&#34;。每行得到的平均值只是MISD属性,因为单个值的平均值是相同的值。
因此,该子句的结果实际上是两行,每行一个:Score节点,MISD值为2.0和8.0。然后你的WHERE子句删除值为8的行(因为它&#39;&gt; = 2),留下sumMis
的2.0。
为确保avg()
函数对所有值执行(而不是获取每个值的平均值:分数节点,这是无用的),您需要在执行{同一点时聚合所有分数{1}},或者当时从范围中移除avg()
。
与Bruno的回答一样,当您执行scores
工作时,从范围中删除scores
。但是,如果每个直接连接:Score节点是一个单独的测试类型,如果你有多个:Score节点直接连接到:Subject by:当前关系,那个查询将采用所有这些的平均值,这可能不是什么你想要的。
理想情况下,您将拥有测试类型的某些属性,这对于avg()
链中的所有节点都是相同的(但与另一个节点不同:直接连接的Score节点:与主题的当前关系)并且您可以将其用作分组键:
:Previous*