我有一组包含足球管理游戏信息的MySQL表。
表格是:
存储在这些表格中的数据与玩家的表现有关。玩家在比赛中进行比赛且具有额定性能(matchRating)。 PlayersMatch中记录了玩家参与的每场比赛,记录了球员当前的状态,比赛表现,比赛时的年龄(出于历史目的)以及他们所处的位置。
现在,目前,我正在使用以下查询列出整个赛季的前10名球员(本赛季整体表现最佳,而不是每轮最佳表现):
SELECT playerID, matchID, playerForm, playerAge, MAX(matchRating)
FROM PlayersMatch
INNER JOIN Matches ON PlayersMatch.matchID = Matches.matchID
WHERE Matches.matchSeason = 35
AND Matches.matchType = 'L'
AND PlayersMatch.position IS NOT NULL
GROUP BY PlayersMatch.playerID
ORDER BY MAX(matchRating) DESC, playerForm ASC
我得到的问题是,当我获得正确的playerID和玩家matchRating时,我得到错误的matchID,表格,年龄和其他信息(即他们来自其他记录)。
我尝试将matchID添加到组中,当我得到正确的信息时,我有重复项,因为它为玩家生成了重复记录(因为playerID和matchID组成了PlayersMatch中的PK)。
非常感谢您对此的帮助。
编辑:经过一些进一步阅读后,我必须正确地编写SQL,并且如果我只有playerID和max(matchRating),则group by才会返回正确的信息 - 在至少是ANSI SQL正确。
在这种情况下,如果我使用max / group by,如何获得该效果的相应匹配详细信息?
编辑2:看起来我有一个有效的查询:
SELECT * FROM PlayersMatch
INNER JOIN
(SELECT playerID, MAX(matchRating)
FROM PlayersMatch p2
JOIN Matches
ON p2.matchID = Matches.matchID
WHERE matchSeason = 35
AND matchType = 'L'
AND p2.position IS NOT NULL
GROUP BY p2.playerID) AS p1
ON PlayersMatch.playerID = p1.playerID
AND PlayersMatch.matchRating = p1.matchRating
JOIN Matches m2
ON PlayersMatch.matchID = m2.matchID
WHERE m2.matchSeason = 35
AND m2.matchType = 'L'
AND PlayersMatch.position IS NOT NULL
ORDER BY matchRating DESC
现在唯一的问题是运行需要21秒。这个查询看起来是否正确?
答案 0 :(得分:1)
仅基于MatchID在PlayersMatch上添加第二个索引,用于初步资格加入到匹配。在matchSeason的Matches表中添加一个索引并输入。
从您的编辑和发布的数据示例中,我认为这将解析为获得第一个“匹配”,该匹配在相同的“排名”下限定跨越的多个实例。所以,再次,内心最好的MatchRating,因为你的“MAX()”显然正在寻找最高评级。从那以后,它将立即重新加入玩家匹配并获得具有相同评级的该人的第一个匹配ID。最后,要关闭它,我们可以直接加入到人员的名称信息,并根据找到的第一个匹配ID匹配,所以不应该返回重复...最终结果按匹配排名进行排序。
SELECT STRAIGHT_JOIN
Players.PlayerName,
M2.*,
PM.MatchRating,
PM.PlayerForm,
PM.PlayerAge,
PM.Position
FROM
( select PreMatch.PlayerID,
PreMatch.MaxMatch,
MIN( P3.MatchID ) as FirstMatch
FROM
( SELECT
p2.playerID,
MAX(p2.matchRating) MaxMatch
FROM
Matches
JOIN PlayersMatch P2
ON Matches.MatchID = p2.matchID
AND P2.Position is not null
WHERE
Matches.MatchSeason = 35
AND Matches.MatchType = 'L'
GROUP BY
p2.playerID ) PreMatch
JOIN PlayersMatch P3
ON PreMatch.PlayerID = P3.PlayerID
AND PreMatch.MaxMatch = P3.MatchRating
AND P3.Position is not null
JOIN Matches M2
on P3.MatchID = M2.MatchID
AND M2.MatchSeason = 35
AND M2.MatchType = 'L'
GROUP BY
PreMatch.PlayerID,
PreMatch.MaxMatch
) AS p1
JOIN Players
on P1.PlayerID = Players.PlayerID
JOIN PlayersMatch PM
on p1.FirstMatch = PM.MatchID
ORDER BY
p1.MaxMatch DESC
答案 1 :(得分:0)
聚合仅适用于应用它的实际列。它不是基于记录的。它确实选择评级的最大值,但不确定如何聚合其他列。
所以当你有记录时:
player 1 | match 1 | 10
player 1 | match 2 | 5
并且您按玩家对它们进行分组,它只需要为“匹配”字段选择一个值,但是哪个未定义:它不依赖于其他列中的聚合。
对于你想要做的事,你需要一个子查询:
SELECT p1.playerID, p1.matchID, p1.playerAge, MAX(p1.matchRating)
FROM PlayersMatch P1
JOIN PlayersMatch p2 on p1.id =
(SELECT id
FROM PlayerMatch p2
WHERE p2.playerId = p1.playerId
ORDER BY MAX(p2.matchRating) DESC
LIMIT 1)
GROUP BY playerID
请注意,我已经为playersmatch-table引入了一个生成的主键(因为我不确定复合键的连接语法和一般有利的单字段人工键。)你仍然可以有一个唯一的约束on(playerID,matchId)。