1

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

游戏玩家

(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
4

1 回答 1

2

您编写的内容称为相关子查询,它强制 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 只输出一行。

没有要多次重新执行的子查询,它只是将匹配项连接到其他表中的相应行一次。但是我会使用外连接,以防比赛中任何一种类型的玩家都没有注册。

然后,我不使用 COUNT(),而是使用 MySQL 的技巧,并在 SUM() 函数中使用带有布尔表达式的 SUM()。MySQL 中的布尔表达式总是返回 0 或 1。它们的 SUM() 与表达式返回 true 的 COUNT() 相同。这样,我只需扫描一次 Gamers 表就可以得到专家和新手的“计数”。


PS MySQL 以非标准方式从布尔表达式返回 0 或 1。标准 ANSI SQL 不支持这一点,许多其他品牌的 RDBMS 也不支持。标准情况下,布尔表达式返回一个布尔值,而不是整数。

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

SUM(CASE G.experience WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END) AS ExpertsSignedUp
于 2013-04-01T16:21:15.760 回答