1

这个问题在某种程度上是对我之前的问题的跟进。它还基于SQLZOO 的“SELECT 中的 SELECT 教程”。这次是关于Task# 8

首先,一个可接受的解决方案:

SELECT w1.name, w1.continent FROM world w1
WHERE w1.population > ALL(
SELECT w2.population*3 FROM world w2
WHERE w2.continent=w1.continent and w2.name<>w1.name)

这一次,相关查询在逻辑中根深蒂固。

仅使用 JOIN(s)仍然可以合理地重写此查询吗?应该是吗?

4

2 回答 2

2

所以任务 8 说:一些国家的人口是任何邻国(在同一大陆)的三倍以上。给国家和大洲。

我觉得有点不清楚。哪些是邻居?这就是大陆上所有的国家吗?如果是,那么下一个问题是我们是否与最小邻居或最大邻居进行比较。假设它是最大的邻居。然后查询将是这样的

select name, continent
  from world w1
 where w1.population > (select max(3*w2.population) 
                          from world w2
                         where w2.continent =  w1.continent
                           and w2.name      <> w1.name)

否则,如果它是所有邻居的 3 倍,那就是这个

select name, continent
  from world w1
 where w1.population > (select 3*sum(w2.population) 
                          from world w2
                         where w2.continent =  w1.continent
                           and w2.name      <> w1.name)

希望能帮助到你。

编辑:Oracle SQL 手册 (E26088-01) 说关于 ALL 功能:

将值与列表中的每个值或查询返回的值进行比较。

例子:

SELECT * FROM employees
WHERE salary >=
ALL ( 1400, 3000)
ORDER BY employee_id;

首先进行聚合,然后进行比较,我们将其简化为一个比较。给定示例表中的结果是相同的。但是针对所有国家的查询实际上可能会给出不同的结果。所以毕竟我必须说你的查询更好。如果您在一个大陆上有一个人口为 1 mio、3.5 mio 和 11 mio 的国家,那么实际上第二个国家是第一个国家的 3 倍,第三个国家是第二个国家的 3 倍。我的查询只会将第二个国家与第三个国家进行比较,但您的查询也会将第一个国家与第二个国家进行比较。

于 2013-02-21T17:51:20.350 回答
1

对于此特定查询,您需要每个大陆上的最大值和第二大值。我会用窗口函数来解决这个问题:

select w.continent,
       max(case when seqnum = 1 then w.name end) as name
from (select w.*, 
             row_number() over (partition by continent order by population desc) as seqnum
      from world w
     ) w
where seqnum in (1, 2)
group by continent
having max(case when seqnum = 1 then population end) > 3*max(case when seqnum = 2 then population end)

好的,考虑到问题的来源,我承认这可能有点先进。

因此,这是一种使用连接而不是相关子查询的方法:

我认为以下是你的逻辑:

select w.name, w.continent
from world w join
     (SELECT w.continent, maxpopulation,
             max(case when population <> maxpopulation then population end) as secondmax
      FROM world w join
           (select continent, max(population) as maxpopulation
            from world
            group by continent
           ) c
           on w.continent = c.continent
      group by w.continent, maxpopulation
     ) wc
     on w.continent = wc.continent and w.population = maxpopulation
where population >= 3*secondmax

所以答案是“是的,你可以在没有相关子查询的情况下做到这一点。” 在最常见的情况下,您可以使用联接和分组依据重写相关子查询。

于 2013-02-21T17:37:03.840 回答