【问题标题】:How to extract top populate city from a SQL query如何从 SQL 查询中提取人口最多的城市
【发布时间】:2021-11-04 05:46:48
【问题描述】:

我在 SQL 数据库中有一组表:

  • states={id, name}:
id name.
1 PACA
2 Ile de France
  • counties={id, name, state_id},
id name state_id
1 Paris. 2
2 Bouches du Rhône 1
3 Var 1
  • cities={id, name, population,county_id}
id name population county_id
1 Paris 2000000 1
2 Marseille  1900000 2
3 Toulon 952000 2
4 Hyères 52575 2

并且能够按县提取人口最多的城市,即:

city_name most_populated county_name
Paris. 2000000. Paris.
Marseille 1900000. Bouches.

尝试执行此查询,但没有成功:

SELECT c.id cid, c.name, ci.name, 
    (SELECT sci.population FROM counties sc JOIN cities sci
        ON sc.id = sci.county_id
        WHERE sc.id = cid
        ORDER BY sci.population DESC
        LIMIT 1) AS city_most_populated
FROM counties c JOIN cities ci ON c.id = ci.county_id
GROUP BY c.id;

结果不是我预期的,不知道如何实现这种查询。

谢谢帮助

【问题讨论】:

  • 您的 GROUP BY 无效,并且会在较新的 MySQL 版本上引发错误(除非在兼容模式下。)
  • 轻松为您提供帮助,同时向我们展示示例表数据(与您想要的结果相匹配)。即minimal reproducible example.
  • 是的...确实...
  • MySQL 5.x 还是 MySQL 8?
  • @MatBailie 服务器版本 5.7

标签: mysql sql


【解决方案1】:

从 MySQL 5.x (没有ROW_NUMBER(),您可以将相关子查询移至JOIN

  • 在相关子查询中查找人口最多的城市
  • 只加入那个城市

注意:如果两个城市与一个县中人口最多的城市并列,那么您想要发生的事情就很模糊了。下面的查询选择每个县人口最多的城市,然后如果与人口最多的城市有联系,它会根据id 任意选择其中一个。

SELECT
  c.id cid,
  c.name,
  ci.name,
  ci.population
FROM
  counties c
JOIN
  cities ci
    ON ci.id = (
      SELECT id
        FROM cities
       WHERE county_id = c.id  -- This is what makes it "correlated", it's similar to joining the query to the counties table
    ORDER BY population DESC, id DESC
       LIMIT 1
    )

在此查询中,有 两个cities 表的引用。这使相关的子查询能够处理每个县的所有城市,然后返回一个id,从而允许对另一个cities 引用的连接恰好在一行上。 (对同一个表有两个引用也需要使用别名。)

演示:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=73e93e61f88efee11e02f1e832c8510b

编辑:

我有ON c.id =,但那是一个错字。

  • 现在更正为ON ci.id =

【讨论】:

  • 好吧,我不知道 MySQL 接受 JOIN 子句中的子查询
  • @Jean-LucAubert 有一个错字,抱歉,现在更正了。我还包含了一个演示,以表明 MySQL 5.7 确实允许在连接谓词中进行相关子查询。
【解决方案2】:

你会使用row_number():

SELECT cc.*
FROM (SELECT c.id as cid, c.name as country_name, ci.name as city_name,
             ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY ci.population DESC) as seqnum
      FROM counties c JOIN
           cities ci
           ON c.id = ci.county_id
     ) cc
WHERE seqnum = 1;

【讨论】:

    【解决方案3】:

    如果您使用的是 MySQL 8+,请在此处使用 ROW_NUMBER

    WITH cte AS (
        SELECT c.id AS city_name, c.population, cn.name AS county_name,
               ROW_NUMBER() OVER (PARTITION BY cn.id ORDER BY c.population DESC) rn
        FROM cities c
        INNER JOIN counties cn ON cn.id = c.county_id
    )
    
    SELECT city_name, population, county_name
    FROM cte
    WHERE rn = 1;
    

    【讨论】:

      猜你喜欢
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多