MySQL查询,两个不同表的计数之间相减

时间:2019-06-21 12:59:55

标签: mysql

我有4个MySQL表:

设计师idname

游戏idnamedesigner_id

开始idgame_id

完成idgame_id

游戏开始时,我的应用向started添加了一行。游戏结束后,它将向finished添加一行。我想获得按设计师名称分组的已开始但尚未完成的游戏的总数。这是我到目前为止的内容:

SELECT designer.name, COUNT(started.game_id) AS total FROM started 
  LEFT JOIN game ON started.game_id = game.id 
  LEFT JOIN designer ON game.designer_id = designer.id 
  GROUP BY designer.name  

这将使我获得启动游戏的总数,并按其设计师分组。但这并没有考虑到我只想开始而不是结束游戏这一事实。

我试图减去总数,就像这样:

SELECT designer.name, (COUNT(started.game_id) - COUNT(finished.game_id)) AS total 
  FROM started 
  LEFT JOIN game ON started.game_id = game.id 
  LEFT JOIN designer ON game.designer_id = designer.id 
  LEFT JOIN finished ON finished.game_id = started.game_id
  GROUP BY designer.name 

尽管开始的游戏比完成的游戏多,但这返回的总数为0

示例数据:

设计师

id | name
--------------
1  | Jim Smith

游戏

id | name | designer_id
-----------------------
1  | Test | 1

开始

id | game_id
------------
1  | 1
2  | 1
3  | 1
4  | 1

完成

id | game_id
------------
1  | 1
2  | 1

4 个答案:

答案 0 :(得分:1)

首先,我建议更改您的数据库设计,并将启动表和完成表转换为一个,并使用状态字段定义游戏是否完成(这只是您可以忽略所有内容的建议)

这可能对您有帮助:

Select name as dname , count(*) from designer where id in 
(Select designer_id from game where id in 
(Select started.id from started where started.gameid not in 
(Select finished.gameid from finished))) 
group by dname 

答案 1 :(得分:0)

遵循SQL可能会帮助您

SELECT designer.name, COUNT(started.game_id) AS total 
FROM started 
LEFT JOIN game ON started.game_id = game.id 
LEFT JOIN designer ON game.designer_id = designer.id 
LEFT JOIN finished ON finished.game_id = started.game_id
WHERE finished.id IS NULL
GROUP BY designer.name 

答案 2 :(得分:0)

如果我正确理解您的工作,则想通过designer.name来了解未完成的游戏数量。您想要这样的东西:

SELECT Games.name, Count(Games.id) AS GamesNotFinished
FROM
(SELECT designer.name, game.id
  FROM started 
  INNER JOIN game ON started.game_id = game.id 
  LEFT JOIN designer ON game.designer_id = designer.id 
  LEFT JOIN finished ON finished.game_id = started.game_id
WHERE finished.game_id IS NULL) AS Games
GROUP BY Games.name

在发表评论后,我在Db Fiddler中创建了一个简单的工作示例,表明它确实有效(“ WHERE finish.game_id IS NULL”子句仅显示那些不存在的示例)。请尝试一下在here

也就是说,回头看表,我很明白为什么您需要两个表来仅管理两个状态。 在游戏表中添加int类型的两列,即“ started”和“ finished”,可能会更好。

然后,您的应用程序可以简单地将启动数设置为1,完成时设置为1,然后您的选择将简单地检查桌面游戏,其中开始数= 1并且完成数= 0,我错了吗?

希望有帮助。

答案 3 :(得分:0)

不存在:

SELECT s.game_id FROM started s
WHERE NOT EXISTS (
  SELECT 1 FROM finished
  WHERE game_id = s.game_id
) 

或具有左联接:

SELECT s.game_id 
FROM started s LEFT JOIN finished f
ON f.game_id = s.game_id
WHERE f.id IS NULL

您可以获取所有已开始但尚未完成的游戏ID。
然后,通过仅加入designergame这样的方式,使用上述两个查询中的任何一个来获取所需的结果:

SELECT 
  d.name, 
  COUNT(g.id) AS total 
FROM designer d INNER JOIN game g
ON d.id = g.designer_id
WHERE g.id IN (
  SELECT s.game_id FROM started s
  WHERE NOT EXISTS (
    SELECT 1 FROM finished
    WHERE game_id = s.game_id
  ) 
)
GROUP BY d.id, d.name