【问题标题】:When combining multiple queries into one how do you sum columns together将多个查询合并为一个时,如何将列相加
【发布时间】:2014-06-20 13:17:56
【问题描述】:

我正在尝试根据比赛表计算联赛排名。

+----------------------------------+
|              Matches             |
+----------------------------------+
| id                               |
| league_id (FK League)            |   
| season_id (FK Season)            |
| home_team_id (FK Team)           |
| away_team_id (FK Team)           | 
| home_score                       |
| away_score                       |
| confirmed                        |
+----------------------------------+

我可以使用此查询正确计算主场联赛排名:

SELECT team.name, home_team_id AS team_id,
    COUNT(*) AS played,
    SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS won,
    SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS lost,
    SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) AS drawn,
    SUM(home_score) AS goalsFor,
    SUM(away_score) AS goalsAgainst,
    SUM(home_score - away_score) AS goalDifference,
    SUM((CASE WHEN home_score > away_score THEN 3 WHEN home_score = away_score THEN 1 ELSE 0 END)) AS points
FROM matches
INNER JOIN team ON matches.home_team_id = team.id
WHERE league_id = 94
    AND season_id = 82
    AND confirmed IS NOT NULL
GROUP BY home_team_id
ORDER BY POINTS DESC;

以及使用此查询的客场联赛标准:

SELECT team.name, away_team_id AS team_id,
    COUNT(*) AS played,
    SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS won,
    SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS lost,
    SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) as drawn,
    SUM(away_score) AS goalsFor,
    SUM(home_score) AS goalsAgainst,
    SUM(away_score - home_score) AS goalDifference,
    SUM((CASE WHEN away_score > home_score THEN 3 WHEN away_score = home_score THEN 1 ELSE 0 END)) AS points
FROM matches
INNER JOIN team ON matches.away_team_id = team.id
WHERE league_id = 94
    AND season_id = 82
    AND confirmed IS NOT NULL
GROUP BY away_team_id
ORDER BY points DESC;

但是使用 UNION ALL 结合这两个查询我没有得到正确的结果

SELECT * FROM 
(
    SELECT team.name, home_team_id AS team_id,
        COUNT(*) AS played,
        SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS won,
        SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS lost,
        SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) AS drawn,
        SUM(home_score) AS goalsFor,
        SUM(away_score) AS goalsAgainst,
        SUM(home_score - away_score) AS goalDifference,
        SUM((CASE WHEN home_score > away_score THEN 3 WHEN home_score = away_score THEN 1 ELSE 0 END)) AS points
    FROM matches
    INNER JOIN team ON matches.home_team_id = team.id
    WHERE league_id = 94
        AND season_id = 82
        AND confirmed IS NOT NULL
    GROUP BY home_team_id
UNION
    SELECT team.name, away_team_id AS team_id,
        COUNT(*) AS played,
        SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS won,
        SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS lost,
        SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) as drawn,
        SUM(away_score) AS goalsFor,
        SUM(home_score) AS goalsAgainst,
        SUM(away_score - home_score) AS goalDifference,
        SUM((CASE WHEN away_score > home_score THEN 3 WHEN away_score = home_score THEN 1 ELSE 0 END)) AS points
    FROM matches
    INNER JOIN team ON matches.away_team_id = team.id
    WHERE league_id = 94
        AND season_id = 82
        AND confirmed IS NOT NULL
    GROUP BY away_team_id
) x 
GROUP BY team_id
ORDER BY points DESC;

这应该是预期的结果:

知道我做错了什么吗?谢谢!

更新 1:

尝试 Dans 查询不起作用:

选择球队名称、主场积分 + 客场积分 从团队加入( 选择team.id, 总和(当 home.home_score > home.away_score 然后 3 的情况 当 home.home_score = home.away_score 然后 1 else 0 end) HomePoints, 总和(当 away.away_score > away.home_score 然后 3 else 0 end 时的情况)AwayPoints 来自团队 在 team.id = home.home_team_id 上加入比赛 在 team.id = away.away_team_id 上加入比赛 在哪里 home.league_id = 94 和 home.season_id = 82 AND home.confirmed 不为空 按 ID 分组 ) team.id 上的温度 = temp.id 按点顺序排列;

我得到这个结果:

【问题讨论】:

  • 您的预期结果包括未被选中的字段。
  • @DanBracuk 在查看预期结果时,请仅考虑“P W ... PTS”部分。这张图片来自我使用的一种旧方法,我有一个 LeagueStanding 表,并在每次使用 PHP 比赛后更新值,但我计划的新功能迫使我改用数据库查询。
  • 请稍等,我将更新查询以显示姓名。

标签: mysql sql union-all


【解决方案1】:

试试这个:

SELECT team.name, 
       team_id AS team_id,
       COUNT(*) AS played,
       SUM((CASE WHEN team_score > other_team_score THEN 1 ELSE 0 END)) AS won,
       SUM((CASE WHEN team_score < other_team_score THEN 1 ELSE 0 END)) AS lost,
       SUM((CASE WHEN team_score = other_team_score THEN 1 ELSE 0 END)) AS drawn,
       SUM(team_score) AS goalsFor,
       SUM(other_team_score) AS goalsAgainst,
       SUM(team_score - other_team_score) AS goalDifference,
       SUM((CASE WHEN team_score > other_team_score THEN 3 
                 WHEN team_score = other_team_score THEN 1 
                 ELSE 0 END)) AS points
FROM
    (
        -- LIST TEAM STATS WHEN PLAYED AS HOME_TEAM
        SELECT 
             id                               
             league_id
             season_id
             home_team_id as team_id,
             home_score   as team_score,
             away_score   as other_team_score, 
             confirmed 
        FROM    matches
        UNION ALL
        -- LIST TEAM STATS WHEN PLAYED AS AWAY_TEAM
        SELECT 
             id                               
             league_id
             season_id
             away_team_id as team_id,
             away_score   as team_score,
             home_score   as other_team_score, 
             confirmed 
        FROM matches
    ) matches
INNER JOIN team ON matches.team_id = team.id
WHERE league_id = 94
    AND season_id = 82
    AND confirmed IS NOT NULL
GROUP BY team.name, team_id
ORDER BY POINTS DESC;

【讨论】:

    【解决方案2】:

    您可能想使用 JOIN 而不是 UNION。 在对都具有 team_id 的子查询使用 UNION 之后,您在 team_id 上使用 GROUP BY。 那是行不通的……如果你只使用join,你甚至可以将group by 排除在外。

    【讨论】:

      【解决方案3】:

      我想我知道发生了什么,但没有安装 MySQL 来测试它。

      当您进行分组查询时,不是分组分组子句一部分的每一列必须是一个聚合函数(SUM、MAX 等)。如果您不这样做,大多数数据库引擎都会给您一个错误; MySQL试图提供帮助?通过选择随机行来代替。

      tl;dr 您的外部选择需要一堆 SUM,而不仅仅是选择 *。

      【讨论】:

      • 它选择它首先在磁盘上遇到的任何值。
      【解决方案4】:

      我会使用这种方法。我只是要做点。你想要的其他东西的逻辑是一样的。

      select TeamName, HomePoints + AwayPoints points
      from team join (
      select team_id
      , sum(case when home.home_score > home.away_score then 3
      when home.home_score = home.away_score then 1 else 0 end) HomePoints
      , sum(case when away.away_score > away.home_score then 3
      when away.home_score = away.away_score then 1 else 0 end) AwayPoints
      from team join matches home on team.team_id = home.home_team_id
      join matches away on team.team_id = away.away_team_id
      where blah blah blah
      group by team_id
      ) temp on team.team_id = temp.team_id
      order by points desc
      

      【讨论】:

      • 谢谢!我明天早上试试。
      • 尝试了这个查询,但它给了我太多的分数(例如,264 代表第一名的团队)
      猜你喜欢
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      • 2017-05-04
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 2019-07-11
      • 1970-01-01
      相关资源
      最近更新 更多