添加左连接后结果减少

时间:2013-06-08 23:27:00

标签: mysql join

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

我正在使用4张桌子......

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

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

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

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

我需要一个查询,它将从matchopponents表中选择每一行,根据opp1id和opp2id区分playeralias,从匹配表中获取匹配标题,然后围绕matchopponent中每个受尊重匹配的平均总评分表。到目前为止我的查询接近预期的结果,但它只返回matchopponents表中的一行。目前我在matchopponents表中有两行:

opp1id opp2id matchid
2 3 11 4 5 12

以下查询返回

Matchtitle Player1 Player2评分 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

2 个答案:

答案 0 :(得分:1)

您在原始查询中缺少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一起使用将确保始终返回选择列表中其他列的预期值。如果您没有GROUP BY或聚合SELECT列表中的项目,您可能会返回意外的结果。 (见MySQL Extensions to GROUP BY

来自MySQL文档:

  

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

答案 1 :(得分: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