1

我正在使用 MYSQL,但在获得我想要的预期结果时遇到了一些麻烦。

我现在正在处理 4 张桌子......

matchopponents
--------------
opp1id
opp2id 
matchid

matches
-------------
id 
title

players
------------
id
playeralias

ratings 
------------
ratingid
ratingvalue
matchid

我需要一个查询,它将从 matchopponents 表中选择每一行,根据 opp1id 和 opp2id 区分 playeralias,从 matches 表中获取比赛标题,然后对 matchopponent 表中每个受尊重的比赛的平均总评分进行四舍五入。到目前为止,我的查询已接近预期结果,但它仅从 matchopponents 表中返回一行。目前我在 matchopponents 表中有 2 行:

opp1id opp2id matchid
2 3 11 4 5 12

以下查询返回

Matchtitle Player1 Player2 Rating MarineKing vs Ryung MarineKing Ryung 3

这对第一行来说很棒......(opp1id 2,opp2id 3,matchid 11)

但是第二行没有返回任何内容......当我删除 LEFT JOIN 评级时,两者都被显示。我已确保所有正确的 ID 均已到位且正确无误。:(

任何有关为什么会发生这种情况的帮助将不胜感激:)

SELECT 
m.title AS "Match Title",
p1.playeralias AS "Player 1",
p2.playeralias AS "Player 2",
ROUND(IFNULL(AVG(r.ratingvalue), 1)) AS "Rating"
FROM 
matchopponents AS MO
JOIN matches AS m ON mo.matchid = m.id
JOIN players AS p1 ON mo.opp1id = p1.id 
JOIN players AS p2 ON mo.opp2id = p2.id
LEFT JOIN ratings r
ON 
r.matchid = mo.matchid
4

2 回答 2

2

您在原始查询中缺少一个GROUP BY子句:

SELECT 
  m.title AS "Match Title",
  p1.playeralias AS "Player 1",
  p2.playeralias AS "Player 2",
  ROUND(IFNULL(AVG(r.ratingvalue), 1)) AS "Rating"
FROM  matchopponents AS MO
JOIN matches AS m ON mo.matchid = m.id
JOIN players AS p1 ON mo.opp1id = p1.id 
JOIN players AS p2 ON mo.opp2id = p2.id
LEFT JOIN ratings r
  ON r.matchid = mo.matchid
GROUP BY m.title, p1.playeraliasp2.playeralias;

由于您正在聚合结果 ( avg()),因此您希望聚合所有行。MySQL 不同,因为它允许使用聚合函数而不包括选择列表中的其他列进行聚合或分组,但结果不一定正确。

将聚合函数与 GROUP BY 一起使用将确保您始终返回选择列表中其他列的预期值。当您不对 SELECT 列表中的项目进行 GROUP BY 或聚合时,可能会返回意外结果。(参见MySQL 对 GROUP BY 的扩展

来自 MySQL 文档:

MySQL 扩展了 GROUP BY 的使用,以便选择列表可以引用未在 GROUP BY 子句中命名的非聚合列。...您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要在每个未在 GROUP BY 中命名的非聚合列中的所有值对于每个组都相同时很有用。服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。在选择了值之后对结果集进行排序,并且 ORDER BY 不会影响服务器选择的值。

于 2013-06-08T23:36:35.937 回答
0

尝试这样的事情:

SELECT 
m.title AS "Match Title",
p1.playeralias AS "Player 1",
p2.playeralias AS "Player 2",
(SELECT ROUND(IFNULL(AVG(r.ratingvalue), 1)) FROM ratings r WHERE r.matchid = mo.matchid LIMIT 1) AS "Rating"
FROM 
matchopponents AS MO
JOIN matches AS m ON mo.matchid = m.id
JOIN players AS p1 ON mo.opp1id = p1.id 
JOIN players AS p2 ON mo.opp2id = p2.id
于 2013-06-08T23:32:34.720 回答