假设橄榄球联赛的结果是通过这种数据得出的:
Date, Round, Home Team, Visitor Team, Result
18/10/2018, 1, ABC, XYZ, 30-20
18/10/2018, 1, PQR, ABC, 13-12
有人可以阐明如何对上述数据进行建模,以找出连续获胜次数最多的球队吗?
答案 0 :(得分:1)
[已更新]
如果我们更改了CSV数据的格式以使其更容易导入(通过修剪多余的空白并更改为更标准的日期格式),则是这样(进行了一些额外的更改以使示例更加有趣):
Date,Round,Home Team,Visitor Team,Result
2018-10-18,1,ABC,XYZ,30-20
2018-10-18,2,ABC,PQR,28-12
2018-10-19,1,PQR,ABC,13-12
然后,我们可以像这样导入数据(使用MERGE
代替CREATE
,以避免创建重复的Team
节点):
LOAD CSV WITH HEADERS FROM 'file:///data.csv' AS row
WITH row, SPLIT(row.Result, '-') AS scores
MERGE (h:Team {name: row.`Home Team`})
MERGE (v:Team {name: row.`Visitor Team`})
CREATE (h)<-[:HOME_TEAM {score: scores[0]}]-(g:Game {date: DATE(row.Date), round: row.Round})-[:AWAY_TEAM {score: scores[1]}]->(v)
我们可以使用此查询返回连续获胜次数最多的球队:
MATCH (t:Team)<-[r]-(g:Game)-[r2]->(t2)
WITH t, r.score > r2.score AS isWin ORDER BY g.date, g.round
RETURN t, REDUCE(s = {max: 0, c: 0, prev:false}, w IN COLLECT(isWin) |
CASE WHEN w
THEN {
c: CASE WHEN s.prev THEN s.c+1 ELSE 1 END,
max: CASE WHEN s.max <= s.c
THEN CASE WHEN s.prev
THEN s.c+1
ELSE CASE WHEN s.max = 0 THEN 1 ELSE s.max END END
ELSE s.max END,
prev: w}
ELSE {c: 0, max: s.max, prev: w} END).max AS maxConsecutiveWins
ORDER BY maxConsecutiveWins DESC
LIMIT 1;
MATCH
模式未指定任何关系类型,因此r
将同时匹配HOME_TEAM
和AWAY_TEAM
关系。
WITH
子句计算每个团队参加的每场比赛的获胜统计数据,并按date
和round
对其进行排序。
由于RETURN
子句使用aggregating function COLLECT
(在REDUCE函数内),因此t
变量用作聚合{{1} }。这导致grouping key
函数一次处理一个团队的所有有序获胜统计信息。
REDUCE
函数的REDUCE
,accumulator
是具有3个属性的地图:
s
是迄今为止发现的最大连续获胜次数。max
是当前获胜顺序的连续获胜次数。c
是上一个游戏的获胜统计数据。由于Cypher没有prev
子句,因此IF
子句用于逻辑分支。 (注意:CASE
子句只能返回一个值-它不能在数据库上执行任何读/写操作)。此查询中的各种CASE
子句用于在依次迭代每个游戏的同时适当地更新CASE
的目的。
在团队的所有比赛中完成accumulator
函数后,REDUCE
子句将获取返回地图的RETURN
值并将其分配给max
变量。
最后一个maxConsecutiveWins
子句按降序对所有ORDER BY
值进行排序,而maxConsecutiveWins
子句只允许返回第一个(值最大的子句)以及与它的相应团队。
使用上述数据的结果将是:
LIMIT
注意:考虑到╒══════════════╤════════════════════╕
│"t" │"maxConsecutiveWins"│
╞══════════════╪════════════════════╡
│{"name":"ABC"}│2 │
└──────────────┴────────────────────┘
子句的复杂性,如果您打算实际使用它,则应在所有可能的边缘情况下测试上述查询。