【问题标题】:joining 3 tables with sum total from two columns meeting a certain criteria连接 3 个表格,其中两列的总和满足特定条件
【发布时间】:2014-06-04 22:56:51
【问题描述】:

假设我有 3 张桌子:

球员 +--------+-------+ |编号 |姓名 | +--------+-------+ | 1 |本 | | 2 |比尔 | | 3 |约翰 | | 4 |休 | | 5 |弗雷德 | +--------|-------+ 游戏1 游戏2 +-----+-------+ +------+--------+ | p_id |积分| | p_id |积分| +-----+-------+ +------+--------+ | 1 | 800 | | 1 | 300 | | 1 | 400 | | 5 | 800 | | 2 | 100 | | 2 | 900 | | 3 | 1000 | | 4 | 1200 | +--------|-------+ +------|--------+

我想将两个表中的总点数相加,按 p_ID 分组,其中总和大于一定数量,例如 1000。所以我希望结果看起来像这样。

查询结果 +--------+---------+---------+--------+ | p_id |积分1 |点2 |总计| +--------+---------+---------+--------+ | 1 | 1200 | 300 | 1500 | | 2 | 100 | 900 | 1000 | | 3 | 1000 | 0 | 1000 | | 4 | 0 | 1200 | 1200 | +--------|---------+---------+--------+

以下是我当前的查询,但没有得到我需要的结果。

SELECT `players`.`p_id`, 
COALESCE(sum(`Game1`.`points`), 0) as 'Game1', 
COALESCE(sum(`Game2`.`points`), 0) as 'Game_2', 
COALESCE(sum(`Game1`.`points`), 0) + COALESCE(sum(`Game2`.`points`), 0) as 'total' 
from `players` 
left join `Game1` on `players`.`p_id`=`Game1`.`p_id` 
left join `Game2` on `players`.`p_id`=`Game2`.`p_id` 
having sum(`Game2`.`points`) + sum(`Game1`.`points`) >= 1000 
order by sum(`Game1`.`points`) + 
sum(`Game2`.`points`) desc

【问题讨论】:

  • 你是不是忘了GROUP BY players.p_id? (MySQL 允许您省略它,通常会产生意想不到的结果,许多其他 RDBMS 只会出错)
  • 这听起来不像有条款吗?

标签: mysql sql


【解决方案1】:

为了使其正常工作,您需要在连接之前进行聚合。否则,您最终会遇到与每个游戏的笛卡尔积相关的问题。

因为 MySQL 不支持full outer join,所以最好的办法是改用union all

select p_id, sum(points1) as points1, sum(points2) as points2
from ((select p_id, points as points1, 0 as points2
       from Game1
      ) union all
      (select p_id, 0, points
       from Game2
      )
     ) g
group by p_id;

【讨论】:

  • 戈登,我不太明白这个论点:在sqlfiddle.com/#!2/a0992/1 中尝试并没有显示出这个......你能详细说明一下吗?我认为这是一些事情,我真的很想完全理解,
  • 算了……我现在明白了!
【解决方案2】:
SELECT
  players.id AS p_id,
  IFNULL(points1,0) AS Game1,
  IFNULL(points2,0) AS Game2,
  IFNULL(points1,0)+IFNULL(points2,0) AS total
FROM players
  LEFT JOIN (
    SELECT p_id, SUM(Game1.points) AS points1
    FROM Game1
    GROUP BY p_id
  ) AS GameSum1 ON players.id=GameSum1.p_id
  LEFT JOIN (
    SELECT p_id, SUM(Game2.points) AS points2
    FROM Game2
    GROUP BY p_id
  ) AS GameSum2 ON players.id=GameSum2.p_id
GROUP BY players.id
HAVING total>=1000
ORDER BY total DESC

编辑

修正了错误的IFNULL()范围,见SQLfiddle

编辑 2

根据@GordonLinoff 的输入修复

【讨论】:

  • 注意COALESCE符合标准
  • 注明。现在请注意,IFNULL() 在 MySQL 中的工作方式相同,并且更具可读性(没有重载)。 IF()CASE WHEN 也可以。 De gustibus non est disbutantur.
  • 其他情况更加灵活,这里不适用。再说一遍:口味不同。
  • Sic transit gloria mundi
  • 你失去了我,但我不认为,我因此失去了一些东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
相关资源
最近更新 更多