-1

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

$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
    ';  
4

1 回答 1

1

我想你想加入teamuser而不是game。我希望该user表有一个team_id(or 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 表并从中查询的开销。(如果这是一个有数十名用户的田径队,这可能会更有效率。但如果它的两个团队(沙滩排球?)它可能不会提高性能。

如果我们采用上面的团队分数查询,我们可以将其包装在括号中并像表格一样使用它。我们还希望包含 team 表中的 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,可以稍微调整查询。并且这些可以在外部查询中加在一起以获得总赢和输。

于 2013-08-21T18:55:23.687 回答