【问题标题】:SQL correlated subquery sequence of eventsSQL相关子查询事件序列
【发布时间】:2016-12-20 02:29:16
【问题描述】:

此查询查找每个大陆按面积计算的最大国家/地区。它显示了大陆、名称和区域。

SELECT
  c1.continent,
  c1.name,
  c1.area
FROM
  countries c1
WHERE
  c1.area = (
        SELECT
          MAX(c2.area)
        FROM
          countries c2
        WHERE
          c1.continent = c2.continent
        )

如果我理解正确,子查询会将每个条目的大陆从 c1 匹配到具有相同大陆的所有 c2 条目并找到最大值。如果是这样,将为 c1 中的每个条目运行子查询。这似乎没有必要吗?

谁能解释一下这个查询中发生的事件顺序以及是否有更好的方法来做到这一点。谢谢。

【问题讨论】:

  • 您使用的是哪个数据库?我的意思是OracleMySQLSQL Server
  • @gordon-linoff 的回答是一个非常好的回答。至于更有效的方法,取决于您的 RDBMS,我建议使用连接的 (SELECT i.name, rownum = ROW_NUMBER() OVER (PARTITION BY i.continent ORDER BY i.area DESC) FROM countries i) 的子查询包括 rownum = 1 在内的标准将为您提供每个大陆上最大的国家/地区的名称。
  • @Aruna 我正在使用 Postgres
  • @Forty3 是的,我这周刚刚学习了 PARTITION,我仍在努力解决这个问题

标签: sql postgresql greatest-n-per-group correlated-subquery


【解决方案1】:

您需要了解 SQL 查询是非过程性的:它们描述的是结果集,而不是如何创建它。

如果countries(continent, area) 上有可用的索引,那么“子查询”只是在索引中查找——一个非常有效的操作。

如果索引不可用,那么一些数据库引擎足够聪明,可以将子查询作为一种连接操作来实现——如果数据足够大,通常使用哈希连接。

诚然,一些数据库会为外部查询中的每一行运行子查询,本质上是执行嵌套循环连接。但并不要求引擎这样做。

【讨论】:

    【解决方案2】:

    Gordon 已经回答了有关如何处理的部分。

    如果您想知道 Postgres 是否将相关子查询重新写入连接 - 请使用 explain (analyze) ... 检查执行计划。


    如果有更好的方法来做到这一点。

    是的,有。使用标准 SQL 时,这通常在使用窗口函数时要快得多:

    select continent, name, area
    from (
      select continent, name, area, 
             dense_rank() over (partition by continent order by area desc) as rnk
      from countries
    ) t
    where rnk = 1;
    

    使用 distinct on () 的 Postgres 通常比使用窗口函数的解决方案更快:

    select distinct on (continent) * 
    from countries 
    order by continent, area desc 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-17
      • 1970-01-01
      • 2022-08-13
      相关资源
      最近更新 更多