mysql赢得损失记录并加入三个表

时间:2013-08-21 18:44:01

标签: mysql

我正在尝试将三张桌子连在一起,这有点复杂。这就是我所拥有的。在尝试选择团队名称之前,它工作正常。此外,如果有人知道如何更有效地计算胜负,那将会有所帮助。

$sql = '
    SELECT u.name, 
        t.name AS team, 
        SUM(
             CASE WHEN (g.awayScore > g.homeScore AND g.away=u.team) 
                 OR (g.homeScore > g.awayScore AND g.home=u.team) 
             THEN 1 ELSE 0 END
        ) AS wins,
        SUM(
             CASE WHEN (g.awayScore < g.homeScore AND g.away=u.team) 
                 OR (g.homeScore < g.awayScore AND g.home=u.team) 
             THEN 1 ELSE 0 END) AS losses
      FROM game AS g
      JOIN user AS u ON g.away = u.team OR g.home = u.team
      JOIN team AS t ON g.away=t.id OR g.home=t.id
      GROUP BY u.name
    ';  

1 个答案:

答案 0 :(得分:1)

我想您想加入team user,而不是game。我希望user表有一个team_id(或team)列,这是一个外键references team(id)

我认为您的查询中唯一需要的更改是一行。只需改变一下:

JOIN team AS t ON g.away=t.id OR g.home=t.id

JOIN team AS t ON t.id = u.team

这应该足以解决问题。


但是我的查询有点不同。像这样:

SELECT u.name
     , t.name AS team
     , SUM(
         CASE WHEN (g.awayScore > g.homeScore AND g.away=t.id)
                OR (g.homeScore > g.awayScore AND g.home=t.id) 
         THEN 1 ELSE 0 END
       ) AS wins
     , SUM(
         CASE WHEN (g.awayScore < g.homeScore AND g.away=t.id)
                OR (g.homeScore < g.awayScore AND g.home=t.id)
         THEN 1 ELSE 0 END
       ) AS losses
  FROM user u
  JOIN team t ON t.id = u.team
  JOIN game g ON g.away = t.id OR g.home = t.id
 GROUP
    BY u.name
     , t.name

备注

我从用户表开始,这就是我们真正想要返回的内容。 (如果我们想为那些不在任何游戏中的团队的用户返回零,那么我们会考虑做一个OUTER JOIN,而我总是写下LEFT JOINS。)

接下来,我会让团队与每个用户相关联。

然后,我加入游戏。这里有点棘手,因为你在比赛中加倍了比赛,一支与客队相匹配,一支与主队相匹配。这也是行数的乘法,一个用于团队中的每个用户。但我们需要这样做,因为我们要把它们全部加起来。

以这种方式编写查询可以非常轻松地按团队获取分数,而无需返回用户:

SELECT t.name AS team
     , SUM(
         CASE WHEN (g.awayScore > g.homeScore AND g.away=t.id)
                OR (g.homeScore > g.awayScore AND g.home=t.id) 
         THEN 1 ELSE 0 END
       ) AS wins
     , SUM(
         CASE WHEN (g.awayScore < g.homeScore AND g.away=t.id)
                OR (g.homeScore < g.awayScore AND g.home=t.id)
         THEN 1 ELSE 0 END
       ) AS losses
  FROM team t
  JOIN game g ON g.away = t.id OR g.home = t.id
 GROUP
    BY t.name

对于大型集合,可能是相当多的行,第一个查询可能会生成大量行,因为每个团队的行都会为团队中的每个用户重复。

因此,另一种方法可能是首先计算团队分数,然后加入用户。但这将需要一个派生表,这是生成临时MyISAM表的开销,然后从中查询。 (如果这是一支拥有数十名用户的赛道团队,这可能会更有效率。但如果它的两队(沙滩排球?)可能不会提高性能。

如果我们采用上面的团队分数查询,我们可以将其包装在parens中并像表格一样使用它。我们还希望包含团队表中的id列,因此我们可以将其连接到外部查询中的users表:

SELECT u.name
     , s.name AS team
  FROM user u 
  JOIN ( SELECT t.id
              , t.name
              , SUM(
                  CASE WHEN (g.awayScore > g.homeScore AND g.away=t.id)
                         OR (g.homeScore > g.awayScore AND g.home=t.id) 
                       THEN 1 ELSE 0 END
                ) AS wins
              , SUM(
                  CASE WHEN (g.awayScore < g.homeScore AND g.away=t.id)
                         OR (g.homeScore < g.awayScore AND g.home=t.id)
                       THEN 1 ELSE 0 END
                ) AS losses
           FROM team t
           JOIN game g ON g.away = t.id OR g.home = t.id
          GROUP BY t.id, t.name
       ) s
    ON s.id = u.team

内联视图(指定了s的别名)与之前的“团队得分”查询基本相同。我们包含team.id列,以便我们可以将其连接到外部查询中的用户表。

- 另一种替代方法:

SELECT u.name
     , t.name AS team
     , SUM(g.wins) AS wins
     , SUM(g.losses) AS losses
  FROM user u
  JOIN team t ON t.id = u.team
  JOIN ( SELECT gh.home AS team
              , SUM(IF(gh.homeScore > gh.awayScore,1,0)) AS wins
              , SUM(IF(gh.homeScore < gh.awayScore,1,0)) AS losses
           FROM game gh
          GROUP BY gh.home
          UNION ALL
         SELECT ga.away AS team
              , SUM(IF(ga.awayScore > ga.homeScore,1,0)) AS wins
              , SUM(IF(ga.awayScore < ga.homeScore,1,0)) AS losses
           FROM game ga
          GROUP BY ga.away
       ) g
    ON g.team = t.id
 GROUP
    BY u.name
     , t.name

内联视图(上面指定了g的别名)分别计算主场胜负和客场胜负,然后将它们连接在一起。如果你想单独返回home_wins,home_losses,away_wins和away_losses,那么查询可能会稍微调整一下。这些可以在外部查询中加在一起,以获得总胜负。