Предположим, результаты лиги регби представлены такими данными:
Date, Round, Home Team, Visitor Team, Result
18/10/2018, 1, ABC, XYZ, 30-20
18/10/2018, 1, PQR, ABC, 13-12
Может ли кто-нибудь пролить свет на то, как смоделировать приведенные выше данные, чтобы определить команду с наибольшим количеством последовательных побед?





[ОБНОВЛЕНО]
Если мы изменим формат ваших данных 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 используется агрегатная функцияCOLLECT (в функции УМЕНЬШАТЬ), переменная t используется в качестве агрегированного grouping key. Это заставляет функцию REDUCE обрабатывать всю упорядоченную статистику выигрышей для одна команда за раз.
REDUCE функции accumulator, s, представляет собой карту с 3 свойствами:
max - это подсчет максимум последовательных побед, обнаруженных на данный момент.c - это количество последовательных выигрышей для последовательности выигрышей Текущий.prev - статистика выигрышей для игры предыдущий.Поскольку Cypher не имеет предложения IF, предложение CASE используется для логического ветвления. (Примечание: предложение CASE может возвращать только значение - оно не может выполнять какие-либо операции чтения / записи в БД). Различные предложения CASE в этом запросе служат для обновления accumulator соответствующим образом при итерации по каждой игре по порядку.
Когда функция REDUCE выполняется со всеми играми для команды, предложение RETURN берет значение max возвращенной карты и присваивает его переменной maxConsecutiveWins.
Последнее предложение ORDER BY сортирует все значения maxConsecutiveWins в порядке убывания, а предложение LIMIT просто позволяет возвращать первое (с наибольшим значением) вместе с соответствующей командой.
Результат с приведенными выше данными будет:
╒══════════════╤════════════════════╕
│"t" │"maxConsecutiveWins"│
╞══════════════╪════════════════════╡
│{"name":"ABC"}│2 │
└──────────────┴────────────────────┘
ПРИМЕЧАНИЕ. Учитывая сложность предложений CASE, вы должны протестировать вышеуказанный запрос со всеми возможными крайними случаями, если вы действительно планируете его использовать.
Спасибо. Неужели ему тоже нужна переменная max? Почему нельзя обойтись только переменной c? Пример: выполнить подсчет для c, если предыдущее совпадение потеряно, сбросить 'c' на '0'
max необходим, поскольку у команды может быть последовательность побед, за которыми следуют проигрыши / ничьи, за которыми следует другая последовательность побед и так далее. Любая последовательность может быть самой длинной. Без отслеживания найденного max ваш результат будет неправильно всегда возвращать длину последовательности побед последний.
Не могли бы вы подробнее объяснить ответ CQL?