如何编写涉及子查询的以下SQL查询

时间:2015-11-21 19:15:01

标签: mysql sql

我有以下名为population的表:

╔════════════╦════════════╦════════════════╗
║     india  ║ hyderabad  ║          50100 ║
║     india  ║ delhi      ║          75000 ║
║     USA    ║ NewYork    ║          25000 ║
║     USA    ║ california ║          30000 ║
║     india  ║  delhi     ║           5000 ║
║     USA    ║  NewYork   ║          75000 ║
╚════════════╩════════════╩════════════════╝

我需要编写一个SQL查询来获取以下格式的数据:

╔════════╦═════════╦══════════╗
║ india  ║ delhi   ║    80000 ║
║ USA    ║ NewYork ║   100000 ║
╚════════╩═════════╩══════════╝

国家/地区名称和人口最多的城市,其中汇总了多个城市条目。感谢Advandce。

3 个答案:

答案 0 :(得分:3)

您可以使用:

SELECT *
FROM (
  SELECT country,city, SUM(pop) AS total
  FROM population 
  GROUP BY country,city) AS sub
WHERE (country, total) IN (
                           SELECT country, MAX(total)
                           FROM (SELECT country,city, SUM(pop) AS total
                                 FROM population 
                                 GROUP BY country,city
                             ) as s
                           GROUP BY country
                           );

如果同一个国家/地区的两个城市拥有相同的最高总人口,您将获得该国家/地区的两个城市。

SqlFiddleDemo

输出:

╔══════════╦═════════╦════════╗
║ country  ║  city   ║ total  ║
╠══════════╬═════════╬════════╣
║ india    ║ delhi   ║  80000 ║
║ USA      ║ NewYork ║ 100000 ║
╚══════════╩═════════╩════════╝

答案 1 :(得分:1)

您可以使用GROUP_CONCAT和FIND_IN_SET的组合。此查询将返回以逗号分隔的每个国家/地区的城市列表,按人口DESC排序:

SELECT country, GROUP_CONCAT(city ORDER BY pop DESC) AS cities
FROM population
GROUP BY country

它将返回如下内容:

| country |                   cities |
|---------|--------------------------|
|   india |    delhi,hyderabad,delhi |
|     USA | NewYok,california,NewYok |

然后我们可以使用FIND_IN_SET将此子查询连接回填充表,该FIND_IN_SET返回城市列表中城市的位置:

SELECT
  p.country,
  p.city,
  SUM(p.pop)
FROM
  population p INNER JOIN (
    SELECT country, GROUP_CONCAT(city ORDER BY pop DESC) AS cities
    FROM population
    GROUP BY country
  ) m ON p.country=m.country
         AND FIND_IN_SET(p.city, m.cities)=1
GROUP BY
  p.country,
  p.city

加入只会在每个国家/地区拥有最多人口的城市成功:FIND_IN_SET(p.city, m.cities)=1

只有当一个城市拥有最大限制时才会有效,如果只有一个城市将被退回。这也不是标准的SQL,只适用于MySQL或类似的,其他DBMS具有窗口函数,可以使同一个查询更容易编写。

答案 2 :(得分:-1)

以下答案不正确,因为它使用了特定于Mysql的功能,违反了ANSI标准。结果不具有确定性,因为未定义在按国家/地区汇总时将返回哪个城市名称。大多数情况下,它是第一个将被使用的条目,这就是为什么在内部查询中进行排序使得大多数情况下都可以使用它。但要注意:根据定义,不能保证使用第一个城市,因此可能会出现输出错误结果的情况。 这个答案没有涵盖的另一个案例是,当一个国家有两个人口与最大人口相同的城市时。该解决方案每个国家仅输出一个城市。

我会用内部子查询解决它,它将所有城市分组,外部过滤器只能按国家/地区获得最大。

SELECT 
  country, city, MAX(population_total) AS population_total
FROM 
  (
        SELECT country, city, SUM(population) AS population_total
        FROM tableName
        GROUP BY country, city
        ORDER BY population_total DESC
  ) AS t1
GROUP BY 
  country