Neo4j在链接在一起的节点上对相同属性执行平均操作

时间:2018-03-01 16:14:31

标签: neo4j cypher

我有一个遵循这种形式的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

我无法弄清楚通过可变数量关系所需的语法,并计算所有相关节点中值之间的平均值。

非常感谢任何帮助。

2 个答案:

答案 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*
相关问题