Я пытаюсь получить матчи соревнований следующего игрока. Игра "gameweek" - это игра, в которой мы играем, и у нас могут быть такие типы gameeeeks: 20, 21, 22, 23. Каждый проигрыватель играет в определенную дату. Теперь все совпадения имеют определенный статус, я могу увидеть, было ли сыграно совпадение определенного игрового поля, если значение статуса равно 5, вместо этого, если оно не сыграно, может иметь статус: 1, 2, 3, 4.
Основная структура проблем и данных
главная проблема: gameweek. Я хочу вернуть следующую игру в матче, который уже играл, так что предположим, что у меня есть следующие совпадения:
| id | round.id | status | gameweek | date
1 488 5 1 1/07/2018
2 488 5 1 1/07/2018
3 488 5 1 1/07/2018
4 488 1 2 7/07/2018
5 488 1 2 7/07/2018
6 488 1 2 7/07/2018
7 488 1 3 16/07/2018
8 488 1 3 16/07/2018
9 488 1 3 16/07/2018
результат должен быть: 7, 8, 9, мой фактический запрос вернет это правильно, но предположим, что все matches
имеют status
5 (так что все matches
сыграли), запрос вернет пустой результат.
Поэтому я попытался справиться с этой ситуацией, чтобы вернуть последнюю gameweek
(если все matches
round
все сыграли), но я получаю:
SQLSTATE [42000]: Синтаксическая ошибка или нарушение доступа: 1140 В агрегированном запросе без GROUP BY выражение # 1 списка SELECT содержит неагрегированный столбец "y.gameweek"; это несовместимо с sql_mode = only_full_group_by
Это мой запрос:
SELECT m.id, m.round_id, m.datetime,
CASE m.status
WHEN 1 THEN 'scheduled'
WHEN 2 THEN 'postponed'
WHEN 3 THEN 'canceled'
WHEN 4 THEN 'playing'
WHEN 5 THEN 'finished'
END AS match_status,
m.gameweek, m.home_team_id, m.home_team_half_time_score, m.home_team_score,
m.home_extra_time, m.home_penalties, m.away_team_id, m.away_team_half_time_score,
m.away_team_score, m.away_extra_time, m.away_penalties, m.venue_id,
m.venue_attendance, m.aggregate_match_id,
t.name AS home_team_name,
t_info.shield_link AS home_team_shield,
t2.name AS away_team_name,
t2_info.shield_link AS away_team_shield,
c.name AS competition_name,
c.id AS competition_id,
r.name AS round_name
FROM 'match' m
LEFT JOIN team t ON m.home_team_id = t.id
LEFT JOIN team_info t_info ON t.id = t_info.team_id
LEFT JOIN team t2 ON m.away_team_id = t2.id
LEFT JOIN team_info t2_info ON t2.id = t2_info.team_id
LEFT JOIN competition_rounds r ON m.round_id = r.id
LEFT JOIN competition_seasons s ON r.season_id = s.id
LEFT JOIN competition c ON c.id = s.competition_id
WHERE 1 AND m.status IN (1, 2, 3, 4, 5) AND m.round_id IN (:round_id1) AND m.gameweek = (SELECT COALESCE(y.gameweek, MAX(x.gameweek)) gameweek
FROM 'match' x
LEFT JOIN
(SELECT MIN(gameweek) gameweek
FROM 'match'
WHERE status < 5
) y ON y.gameweek = x.gameweek ) ORDER BY m.datetime DESC LIMIT 10
Как я могу это исправить?
Благодарю.
Дополнительные дополнительные сведения
в первой части запроса я выбираю только поля, которые я хочу вернуть из объединенной таблицы. Выбор производится с использованием соответствия главной таблицы, где хранятся все совпадения. У меня есть команда join и team_info, которая берет информацию о двух командах, которые играют в матче.
После этого я присоединяюсь к соревнованиям, которые получают детали раунда, раунд - это просто организация матча, то же самое для сезона, например:
round.name = Regular Season | season.id = 5 season.name = 2017/2018 | id = 5
это не имеет большого значения в этом вопросе, но я пытаюсь объяснить все действия запроса.
В предложении where я получаю все совпадения, которые имеют статус всех доступных состояний: 1, 2, 3, 4, 5 (вы можете найти описание состояния в поле выбора полей запроса). Позже у меня есть фильтр, который возвращает все совпадения, которые являются частью этих раундов: 10, 488, 392, 70.
Это часть вашего запроса, вызывающая проблему:
m.gameweek = (SELECT COALESCE(y.gameweek, MAX(x.gameweek)) gameweek
FROM 'match' x LEFT JOIN
(SELECT MIN(gameweek) gameweek
FROM 'match'
WHERE status < 5
) y
ON y.gameweek = x.gameweek
)
Проблема в том, что y.gameweek
не агрегируется. Вы можете решить эту проблему, добавив GROUP BY y.gameweek
:
m.gameweek = (SELECT COALESCE(y.gameweek, MAX(x.gameweek)) gameweek
FROM 'match' x LEFT JOIN
(SELECT MIN(gameweek) gameweek
FROM 'match'
WHERE status < 5
) y
ON y.gameweek = x.gameweek
GROUP BY y.gameweek
)
Однако более простое выражение:
m.gameweek = (SELECT m2.gameweek
FROM 'match' m2
ORDER BY (status < 5) DESC,
(CASE WHEN status < 5 THEN gameweek END) ASC,
gameweek DESC
LIMIT 1
)
Первый ключ ORDER BY
сначала помещает строки со status < 5
. Второй заказывает их с помощью gameweek
в порядке возрастания. Таким образом, результатом этого является то, что первая строка будет иметь status < 5
с минимальным значением gameweek
.
Ни один из них не существует, тогда третий ключ вступает в игру, и вы получаете максимальное значение.
В другой версии используется условная агрегация:
m.gameweek = (SELECT COALESCE(MIN(CASE WHEN m2.status < 5 THEN m2.gameweek END),
MAX(m2.gameweek)
)
FROM 'match' m2
)