【问题标题】:SQL: count from same table/field, but different valuesSQL:从同一个表/字段计数,但值不同
【发布时间】:2013-06-02 19:34:49
【问题描述】:

在我的数据库项目中,我必须建立一个关于奥运会数据的数据库。

我还必须构建以下查询:

计算用户提供的特定奥运会的奖牌表。奖牌表应包含 国家的国际奥委会代码,后跟金牌、银牌、铜牌和奖牌总数。首先应该是 按金、银、铜的数量排序。

基本上,我有一张表Medals,其中包含一些参加者在某项奥运会上获得的奖牌。

奖牌存储方式如下:我的表Medalscolor字段中的“金牌”、“银牌”、“铜牌”。

我尝试使用以下查询:

SELECT q1.country, q1.name as "Game", q1.cntG, q2.cntS, q3.cntB FROM
(
    SELECT c.countryName as country, g.name as name, count(m.idMedal) as cntG 
    FROM Game g
    INNER JOIN Participant p
    ON p.fkGame = g.idGame
    INNER JOIN Country c
    ON p.fkCountry = c.idCountry
    INNER JOIN Medals m
    ON m.fkMedalist = p.idParticipant
    WHERE
    g.name = "2012 Summer Olympics" 
    AND m.color like '%Gold%'
    GROUP BY c.countryName
    ORDER BY c.countryName, cntG DESC
) as q1,
(
    SELECT c.countryName as country, g.name as name, count(m.idMedal) as cntS 
    FROM Game g
    INNER JOIN Participant p
    ON p.fkGame = g.idGame
    INNER JOIN Country c
    ON p.fkCountry = c.idCountry
    INNER JOIN Medals m
    ON m.fkMedalist = p.idParticipant
    WHERE g.name = "2012 Summer Olympics" 
    AND m.color like '%Silver%'
    GROUP BY c.countryName
    ORDER BY c.countryName, cntS DESC
) as q2,
(
    SELECT c.countryName as country, g.name as name, count(m.idMedal) as cntB 
    FROM Game g
    INNER JOIN Participant p
    ON p.fkGame = g.idGame
    INNER JOIN Country c
    ON p.fkCountry = c.idCountry
    INNER JOIN Medals m
    ON m.fkMedalist = p.idParticipant
    WHERE g.name = "2012 Summer Olympics" 
    AND m.color like '%Bronze%'
    GROUP BY c.countryName
    ORDER BY c.countryName, cntB DESC
) as q3
GROUP BY q1.country
ORDER BY q1.cntG, q2.cntS, q3.cntB DESC

嗯,它给了我一个完全奇怪的结果。我知道这个查询有问题,但不知道是什么问题!

希望你能帮助我:)

谢谢

注意:我暂时忽略了查询总数(如作业中所要求的)。一旦我想出构建第一部分,我会尝试全部

【问题讨论】:

  • 以什么方式完全奇怪?
  • 好吧,我已经晚了,但请尝试在 GROUP BY q1.country 之前添加 WHERE q1.country = q2.country AND q1.country = q3.country。效果更好吗?
  • 它似乎没有以独立的方式计算计数。仍然显示一些计数,但它们是错误的(例如美国在某些游戏中赢得了 2200 枚金牌)。我的数据库中的数据不是问题
  • 您尝试了我的建议还是参考了原始代码的结果?
  • @ExpertSystem 就像一个魅力 :) 谢谢!我怎么能不考虑嘿嘿...... edit :我在看到你的答案之前就回复了:)

标签: sql subquery


【解决方案1】:

数据不是问题——在 q1、q2 和 q3 之间存在隐式笛卡尔连接这一事实是个问题。试试:

SELECT c.countryName as country, 
       count(case m.idMedal when 'Gold medal' then 1 end) as cntG,
       count(case m.idMedal when 'Silver medal' then 1 end) as cntS,
       count(case m.idMedal when 'Bronze medal' then 1 end) as cntB
FROM Game g
INNER JOIN Participant p ON p.fkGame = g.idGame
INNER JOIN Country c ON p.fkCountry = c.idCountry
INNER JOIN Medals m ON m.fkMedalist = p.idParticipant
WHERE g.name = "2012 Summer Olympics" 
GROUP BY c.countryName
ORDER BY cntG DESC, cntS DESC, cntB DESC

【讨论】:

  • 我非常喜欢 SUM() 技巧,因为它不那么冗长。
【解决方案2】:

很抱歉,您的查询确实一团糟。您不能以这种方式简单地加入 3 个子查询。

但是,您可以在一个查询中获得所需的内容。我会给你伪代码,把细节留给你:)

SELECT
    [countryName],
    SUM(color like '%Gold%') as total_gold,
    SUM(color like '%Silver%') as total_silver,
    SUM(color like '%Bronze%') as total_bronze,
    COUNT(*) as total
FROM Medals
INNER JOIN Participant (...)
INNER JOIN Country (...)
INNER JOIN Game (...)
WHERE (...)
GROUP BY [countryName]
ORDER BY total_gold DESC, total_silver DESC, total_bronze DESC;

【讨论】:

    【解决方案3】:

    有很多方法可以修复甚至改进您的查询,其中之一就是添加

     ...
     WHERE q1.country = q2.country 
       AND q1.country = q3.country
    

    (就在GROUP BY q1.country 之前)。

    另一种解决方案是在country 上加入 q1、q2 和 q3。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      相关资源
      最近更新 更多