我试图从图表数据库中将连续通过最多的学生返回到一系列考试中。
以下是我当前的代码,但不知道我可以从当前状态中取出它来解决我的问题。
MATCH (s:Student)-[r:TAKEN]->(e:Exam)
RETURN s.name, e.date,
CASE
WHEN r.score >= e.pass_mark THEN 1
END as pass
ORDER BY e.date
我想要一个基本的表格,可以显示学生连续几次连续传球。
例如:
| student | pass/fail |
| joe | pass |
| matt | pass |
| joe | fail |
| matt | pass |
| joe | pass |
| matt | pass |
| joe | pass |
| matt | fail |
我希望我的查询结果能够连续显示每个学生和他们的最高连胜纪录。
| student | passes in a row |
| joe | 2 |
| matt | 3 |
我一直在玩CASE
但是还没有找到一个好的解决方案,目前,它只会列出每个考试的所有学生,如果他们通过了它就会得到1。
答案 0 :(得分:1)
这是一个棘手的问题,据我所知,只有Cypher无法完成,但APOC Procedures中有一个程序可以提供帮助。
apoc.coll.split()
采用一个集合和一个值进行拆分,并为每个生成的子集合生成记录。基本上,我们收集每个学生的有序结果,分为失败以获得连续通过的集合,然后从这些集合的大小获得最大连续通过:
MATCH (s:Student)-[r:TAKEN]->(e:Exam)
WITH s, r.score >= e.pass_mark as passed
ORDER BY e.date
WITH s, collect(passed) as resultsColl
CALL apoc.coll.split(resultsColl, false) YIELD value
WITH s, max(size(value)) as consecutivePasses
RETURN s.name as student, consecutivePasses
答案 1 :(得分:1)
你可以用普通的Cypher来做,但我认为它非常实用 - 你基本上需要用reduce
编写一个程序。
基本上,"分裂"工作原理如下:初始化一个空的累加器列表并通过遍历通过/失败列表来计算条纹,检查当前元素是否与前一个元素相同。例如ViewModel
保留条纹,['pass', 'pass']
打破它。如果它中断(就像在列表的开头一样),则将新元素追加到累加器。如果保持,则将新元素附加到累加器的最后一个元素,例如使用新的['pass', 'fail']
,'fail'
变为[['pass', 'pass'], ['fail']]
。
[['pass', 'pass'], ['fail', 'fail]]
在步骤(1)中,这计算条纹,例如:
UNWIND
[
['joe', 'pass'],
['matt', 'pass'],
['joe', 'fail'],
['matt', 'pass'],
['joe', 'pass'],
['matt', 'pass'],
['joe', 'pass'],
['matt', 'fail']
] AS row
WITH row[0] AS s, row[1] AS passed
WITH s, collect(passed) AS p
WITH s, reduce(acc = [], i IN range(0, size(p) - 1) |
CASE p[i] = p[i-1]
WHEN true THEN [j IN range(0, size(acc) - 1) |
CASE j = size(acc) - 1
WHEN true THEN acc[j] + [p[i]]
ELSE acc[j]
END
]
ELSE acc + [[p[i]]]
END
) AS streaks // (1)
UNWIND streaks AS streak
WITH s, streak
WHERE streak[0] <> 'fail'
RETURN s, max(size(streak)) AS consecutivePasses // (2)
在(2)中,它给出了:
╒══════╤═════════════════════════════════╕
│"s" │"streaks" │
╞══════╪═════════════════════════════════╡
│"matt"│[["pass","pass","pass"],["fail"]]│
├──────┼─────────────────────────────────┤
│"joe" │[["fail"],["pass","pass"]] │
└──────┴─────────────────────────────────┘
当然,在这种特殊情况下,没有必要进行拆分:简单计数就足够了。但在99%的实际情况中,APOC是要走的路,所以我没有打扰优化这个解决方案。