优化mysql查询:奖牌排名

优化mysql查询:奖牌排名,mysql,optimization,Mysql,Optimization,我有两张桌子: 奥运会奖牌获得者,有金牌国家、银牌国家、铜牌国家 带有国家栏的旗帜 我想相应地列出奥运奖牌表。我有这个查询,它工作,但它似乎杀死mysql。希望有人能帮助我优化查询 SELECT DISTINCT country AS sc, IFNULL( (SELECT COUNT(silver_country) FROM olympic_medalists WHERE silver_country = sc AND sil

我有两张桌子:

奥运会奖牌获得者,有金牌国家、银牌国家、铜牌国家

带有国家栏的旗帜

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

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)
结果如下:

country  |  g  |  s  |  b  |  tot
---------------------------------
country1 |  9  |  5  |  2  |  16
country2 |  5  |  5  |  5  |  15
等等

谢谢

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`)

这将比当前为交叉连接关系中的每一行执行三个不同的SELECT子查询的解决方案效率更高,并且您想知道为什么它会暂停!:

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
更快的方法是不在gold、silver和brown列中存储实际的文本国家名称,而是存储基于整数的国家id。整数的比较总是比字符串的比较快

此外,一旦您将奥运会奖牌获得者表中的每个国家名称替换为相应的id,您将希望在每列金牌、银牌和铜牌上创建一个索引

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

尝试以下操作:

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

你能发布你的模式吗?我也不太清楚你说的杀掉mysql是什么意思?“杀掉mysql”-当我运行这个程序时,页面需要一段时间才能加载,这是在本地服务器上进行的。当我在一个实时服务器上运行它时,基本上需要永远的时间来加载,mysql就会死掉。我将把模式添加到帖子中抱歉问这个问题,但是有可能修改您的模式吗?我假设国旗上的varchar是国家或国家代码,这在奥运会奖牌获得者的干预类别中是重复的?如果不重复,更新/插入记录可能会稍微干净一些。也许将国旗改为国家,制作黄金、白银和青铜的连接表,并在其中放置特定信息,如国家id、事件、删除名称等。很抱歉,建议更改您的模式,我知道从长远来看,这并不总是可能,但会使事情变得更简单。这些索引也会有帮助。这真的很快。正是我想要的。谢谢我将尝试遵循您关于存储国家ID而不是国家本身的建议。