繁体   English   中英

使用正确的MYSQL JOIN

[英]Using the right MYSQL JOIN

我正在尝试从比赛表中获取所有数据,以及每种类型的当前注册玩家(无论是否经验丰富)。

玩家

(PK)Gamer_Id
Gamer_firstName,
Gamer_lastName,
Gamer experience(Y/N) 

Gamer_matches

(PK)FK GamerId,
(PK)FK MatchId,
Gamer_score

比赛

(PK)Match_Id,
ExperiencedGamers_needed,
InExperiencedGamers_needed

我已经与许多其他人一起尝试过该查询,但是它不起作用,这是不好的联接吗?

SELECT M.MatchId,M.ExperiencedGamers_needed,M.InExperiencedGamers_needed,
(SELECT COUNT(GM.GamerId) 
FROM Gamers G, Gamers_matches GM
WHERE G.GamerId = GM.GamerId
AND G.experience = "Y"
AND GM.MatchId = M.MatchId 
GROUP BY GM.MatchId)AS ExpertsSignedUp,

(SELECT COUNT(GM.GamerId)
FROM Gamers G, Gamers_matches GM
WHERE G.GamerId = GM.GamerId
AND G.experience = "N"
AND GM.MatchId = M.MatchId
GROUP BY GM.MatchId) AS NovicesSignedUp

FROM MATCHES M

您编写的内容称为相关子查询 ,它强制SQL对从Matches提取的每一行重新执行子查询。 它可以工作,但是效率很低。 在某些复杂的查询中,可能有必要,但在这种情况下则没有必要。

我将以这种方式解决此查询:

SELECT M.MatchId, M.ExperiencedGamers_needed,M.InExperiencedGamers_needed,
  SUM(G.experience = 'Y') AS ExpertsSignedUp,
  SUM(G.experience = 'N') AS NovicesSignedUp
FROM MATCHES M
LEFT OUTER JOIN (Gamer_matches GM
    INNER JOIN Gamers G ON G.GamerId = GM.GamerId)
  ON M.MatchId = GM.MatchId
GROUP BY M.MatchId;

在此,由于末尾的GROUP BY,每个Match仅输出一行。

没有子查询可以重新执行很多次,它只是将Matches连接到其他表中的相应行一次。 但是我使用外部联接,以防万一比赛有eithe类型的零个玩家注册。

然后,我不使用COUNT(),而是使用MySQL的技巧,将SUM()与SUM()函数中的布尔表达式一起使用。 MySQL中的布尔表达式始终返回0或1。它们的SUM()与COUNT()相同,其中表达式返回true。 这样,我只需扫描一次Gamers表即可获得专家和新手的“计数”。


PS MySQL以一种非标准的方式从布尔表达式返回0或1。 标准ANSI SQL不支持此功能,许多其他品牌的RDBMS也不支持此功能。 通常,布尔表达式返回布尔值,而不是整数。

但是,如果您需要编写标准SQL以实现可移植性,则可以使用更冗长的表达式:

SUM(CASE G.experience WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END) AS ExpertsSignedUp

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM