【问题标题】:How to mix AND improve this SQL sentences?如何混合和改进这个 SQL 语句?
【发布时间】:2014-10-27 22:38:40
【问题描述】:

首先,我为 mySQL 使用世界数据库:http://dev.mysql.com/doc/world-setup/en/index.html

我正在尝试构建一个句子,从每个大陆返回人口最少的国家,如果人口相同,则显示每个大陆的所有国家。

通过以下句子,我设法得到了每个大陆上人口最少的一个国家的人口,但只有一个显示,并且该国家/地区显示不正确。

SELECT 
CASE
  WHEN Continent="Europe" THEN "Europe"
  WHEN Continent="Asia" THEN "Asia"
  WHEN Continent="North America" THEN "North America"
  WHEN Continent="South America" THEN "South America"
  WHEN Continent="Africa" THEN "Africa"
  WHEN Continent="Oceania" THEN "Oceania"
  ELSE "Antarctica"
END
  AS Area,
Name,
  CONCAT(MIN(Population),"hb") AS "N habitantes"     
FROM Country
GROUP BY Area;

给出这个结果

'Africa'       , 'Angola'        , '0hb'
'Antarctica'   , 'Antarctica'    , '0hb'
'Asia'         , 'Afghanistan'   , '286000hb'
'Europe'       , 'Albania'       , '1000hb'
'North America', 'Aruba'         , '7000hb'
'Oceania'      , 'American Samoa', '0hb'
'South America', 'Argentina'     , '2000hb'

好吧,代码很愚蠢,我想必须有一种方法可以更好地表明对于每个大陆,查询必须返回人口最少的国家。我想知道它是否存在,因为只有7个大陆可以做到,但如果它们是1000000......

通过这句话,我将能够返回我所指出的大陆上人口最少的国家,例如:

SELECT Name,Population FROM Country WHERE Population=
(SELECT MIN(Population) FROM   Country WHERE Continent="Antarctica");

返回:

'南极洲','0'

'法属南部地区', '0'

'布维岛','0'

'赫德岛和麦克唐纳群岛','0'

'英属印度洋领地', '0'

'南乔治亚和南桑威奇群岛','0'

'美国本土外小岛屿','0'

我认为必须有一种方法可以混合这两个句子,并且它返回的结果与每个大陆的先前结果相似,所以它返回我在开头所说的内容。我的意思是,如果世界上只有南极洲和南美洲的大陆应该将其添加到之前的结果中:

'福克兰群岛','2000'

“诺福克岛”,“2000”

'纽埃','2000'

'托克劳','2000'

我知道我可以使用 UNION 为每个大洲造一个类似于第二个的句子,但再一次,这是可行的,因为只有 7 个大洲。

知道我错过了什么吗?感谢您的帮助。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    要获取每个大陆人口最少的国家/地区的名称,您需要确定这些国家/地区。像这样的东西:-

    SELECT Continent, MIN(Population) 
    FROM   Country
    GROUP BY Continent
    

    这样做的缺点是它不返回国家名称,并且您不能合法地将国家名称添加到查询中(MySQL 不会出错,但结果是不确定的)。

    因此,您可以将上述内容用作子查询并将其与表连接起来,包括大陆名称和人口

    SELECT b.Continent, b.Name, b.Population
    FROM
    (
        SELECT Continent, MIN(Population) AS Population
        FROM Country
        GROUP BY Continent
    ) a
    INNER JOIN Country b
    ON a.Continent = b.Continent
    AND a.Population = b.Population
    

    不利的一面是,如果一个大陆上多个国家拥有相同的人口,那么结果将会很奇怪。

    另一种选择是使用 GROUP_CONCAT 将所有名称按人口顺序放在一起,然后只需使用 SUBSTRING_INDEX 获取第一个:-

    SELECT Continent, SUBSTRING_INDEX(GROUP_CONCAT(Name ORDER BY Population), ',', 1), SUBSTRING_INDEX(GROUP_CONCAT(Population ORDER BY Population), ',', 1)
    FROM Country
    GROUP BY Continent
    

    这种方法的缺点是,如果国家名称包含用作分隔符的字符,那么结果可能会很奇怪(默认为逗号)。

    也可以使用用户变量将序列号添加到按人口排序的大陆内的国家/地区,然后只需获取序列号为 1 的国家/地区。

    【讨论】:

      【解决方案2】:
       SELECT x.continent
            , x.code
            , x.name
            , x.population 
         FROM country x 
         JOIN 
            ( SELECT continent
                   , MIN(population) min_population 
                FROM country 
               GROUP 
                  BY continent
            ) y 
           ON y.continent = x.continent 
          AND y.min_population = x.population;
      

      输出:

      +---------------+------+----------------------------------------------+------------+
      | continent     | code | name                                         | population |
      +---------------+------+----------------------------------------------+------------+
      | Antarctica    | ATA  | Antarctica                                   |          0 |
      | Antarctica    | ATF  | French Southern territories                  |          0 |
      | Antarctica    | BVT  | Bouvet Island                                |          0 |
      | South America | FLK  | Falkland Islands                             |       2000 |
      | Antarctica    | HMD  | Heard Island and McDonald Islands            |          0 |
      | Africa        | IOT  | British Indian Ocean Territory               |          0 |
      | Asia          | MDV  | Maldives                                     |     286000 |
      | Antarctica    | SGS  | South Georgia and the South Sandwich Islands |          0 |
      | North America | SPM  | Saint Pierre and Miquelon                    |       7000 |
      | Oceania       | UMI  | United States Minor Outlying Islands         |          0 |
      | Europe        | VAT  | Holy See (Vatican City State)                |       1000 |
      +---------------+------+----------------------------------------------+------------+
      

      【讨论】:

        【解决方案3】:

        你可以像这样使用 group by:

        SELECT Name,Population FROM Country WHERE Population=
        (SELECT MIN(Population) FROM   Country GROUP BY Continent);
        

        【讨论】:

        • 感谢您的回答,但除非我理解错误,否则它不起作用。首先,子查询返回不止一行,所以它不能被执行,我猜你想把最后一个 ) 放在国家之后,这样它就可以工作,但世界上人口最少的国家不在每个大陆,只是每个大陆显示一个国家/地区。
        猜你喜欢
        • 1970-01-01
        • 2021-03-15
        • 1970-01-01
        • 2011-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-21
        • 2015-07-01
        相关资源
        最近更新 更多