首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优化mysql查询:奖章排名

优化mysql查询:奖章排名
EN

Stack Overflow用户
提问于 2012-08-04 05:42:54
回答 2查看 229关注 0票数 1

我有两张桌子:

  1. 列olympic_medalists ( gold_country、silver_country、bronze_country )
  2. 带国家栏的旗帜

我想相应地列出奥运奖牌表。我有这个查询,它可以工作,但它似乎扼杀了mysql。希望有人能帮助我进行优化查询。

代码语言:javascript
复制
SELECT DISTINCT country AS sc,
    IFNULL(
        (SELECT COUNT(silver_country) 
            FROM olympic_medalists 
        WHERE silver_country = sc AND silver_country != '' 
        GROUP BY silver_country),0) AS silver_medals, 
    IFNULL(
        (SELECT COUNT(gold_country) 
            FROM olympic_medalists 
        WHERE gold_country = sc AND gold_country != '' 
        GROUP BY gold_country),0) AS gold_medals,
    IFNULL(
        (SELECT COUNT(bronze_country) 
            FROM olympic_medalists 
        WHERE bronze_country = sc AND bronze_country != '' 
        GROUP BY bronze_country),0) AS bronze_medals
FROM olympic_medalists, flags 
GROUP BY country, gold_medals, silver_country, bronze_medals HAVING (
    silver_medals >= 1 || gold_medals >= 1 || bronze_medals >= 1)
ORDER BY gold_medals DESC, silver_medals DESC, bronze_medals DESC,   
SUM(gold_medals+silver_medals+bronze_medals)

结果如下:

代码语言:javascript
复制
country  |  g  |  s  |  b  |  tot
---------------------------------
country1 |  9  |  5  |  2  |  16
country2 |  5  |  5  |  5  |  15

诸若此类

谢谢!

代码语言:javascript
复制
olympic medalists:

  `id` int(8) NOT NULL auto_increment,
  `gold_country` varchar(64) collate utf8_unicode_ci default NULL,
  `silver_country` varchar(64) collate utf8_unicode_ci default NULL,
  `bronze_country` varchar(64) collate utf8_unicode_ci default NULL, PRIMARY KEY  (`id`)

flags

  `id` int(11) NOT NULL auto_increment,
  `country` varchar(128) default NULL,
  PRIMARY KEY  (`id`)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-04 06:27:59

这将比当前为交叉连接关系中的每一行执行三个不同的SELECT子查询的解决方案高效得多(您想知道为什么会停下来!):

代码语言:javascript
复制
SELECT    a.country,
          COALESCE(b.cnt,0)     AS g,
          COALESCE(c.cnt,0)     AS s,
          COALESCE(d.cnt,0)     AS b,
          COALESCE(b.cnt,0) +
          COALESCE(c.cnt,0) +
          COALESCE(d.cnt,0)     AS tot
FROM      flags a
LEFT JOIN (
          SELECT   gold_country, COUNT(*) AS cnt 
          FROM     olympic_medalists 
          GROUP BY gold_country
          ) b ON a.country = b.gold_country
LEFT JOIN (
          SELECT   silver_country, COUNT(*) AS cnt 
          FROM     olympic_medalists 
          GROUP BY silver_country
          ) c ON a.country = c.silver_country
LEFT JOIN (
          SELECT   bronze_country, COUNT(*) AS cnt 
          FROM     olympic_medalists 
          GROUP BY bronze_country
          ) d ON a.country = d.bronze_country

更快的不是将实际的文本国家名称存储在每个金、银和青铜列中,而是存储基于整数的country id。对整数的比较总是比字符串上的比较快。

此外,一旦您用相应的id替换了olympic_medalists表中的每个国家名称,您将希望在每一列(黄金、银和青铜)上创建一个索引。

将文本名称更新为相应的id是一项简单的任务,可以使用单个UPDATE语句和一些ALTER TABLE命令来完成。

票数 0
EN

Stack Overflow用户

发布于 2012-08-04 06:36:20

试试这个:

代码语言:javascript
复制
SELECT F.COUNTRY,IFNULL(B.G,0) AS G,IFNULL(B.S,0) AS S,
IFNULL(B.B,0) AS B,IFNULL(B.G+B.S+B.B,0) AS TOTAL
FROM FLAGS F LEFT OUTER JOIN
      (SELECT A.COUNTRY,
         SUM(CASE WHEN MEDAL ='G' THEN 1 ELSE 0 END) AS G,
         SUM(CASE WHEN MEDAL ='S' THEN 1 ELSE 0 END) AS S,
         SUM(CASE WHEN MEDAL ='B' THEN 1 ELSE 0 END) AS B
      FROM   
          (SELECT GOLD_COUNTRY AS COUNTRY,'G' AS MEDAL 
           FROM OLYMPIC_MEDALISTS WHERE GOLD_COUNTRY IS NOT NULL
           UNION ALL
           SELECT SILVER_COUNTRY AS COUNTRY,'S' AS MEDAL 
           FROM OLYMPIC_MEDALISTS WHERE SILVER_COUNTRY IS NOT NULL
           UNION ALL
           SELECT BRONZE_COUNTRY AS COUNTRY,'B' AS MEDAL 
           FROM OLYMPIC_MEDALISTS WHERE BRONZE_COUNTRY IS NOT NULL)A
      GROUP BY A.COUNTRY)B
 ON F.COUNTRY=B.COUNTRY
 ORDER BY IFNULL(B.G,0) DESC,IFNULL(B.S,0) DESC,
          IFNULL(B.B,0) DESC,IFNULL(B.G+B.S+B.B,0) DESC,F.COUNTRY
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11806268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档