使用 min/max 的子查询
Subqueries using min/max
一些国家的人口是其任何邻国(同一大陆)人口的三倍多。给出国家和大洲。
From https://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial, question 10
我试过这个:
SELECT w.name, w.continent
FROM world w
WHERE w.population/3 > (SELECT min(w2.population)
FROM world w2
WHERE w2.continent = w.continent);
这个解决方案似乎有效:
SELECT w.name, w.continent
FROM world w
WHERE w.population > (SELECT 3 * MAX(w2.population)
FROM world w2
WHERE w2.continent = w.continent AND
w2.name <> w.name
);
我试图理解我的解决方案中的逻辑缺陷。
为什么使用 max()
而不是 min()
,因为我们要比较人口是否是非洲大陆人口最少国家的 3 倍?
min/max 场景中是否需要 w2.name <> w.name
。为什么?
more than three times that of any of their neighbours
也就是说,同一个大陆上人口第二多的国家必须少于三分之一,而且每个大陆只有一个国家有资格。 (大陆上的最低人口数不相关。)
第二个查询获取同一大陆上除外部查询 (w2.name <> w.name
) 之外的所有国家/地区,找到人口最多的国家并乘以 3。如果仍然低于该国家/地区的人口外部查询,它通过了条件。
除此之外,虽然优雅 SQL,但查询开销很大,因为 相关子查询 必须计算一次每一行。这个应该更便宜:
SELECT *
FROM (
SELECT DISTINCT ON (continent)
name, continent, population
, lead(population) OVER (PARTITION BY continent ORDER BY population DESC) AS next_population
FROM world
ORDER BY continent, population DESC
) sub
WHERE population > 3 * next_population;
db<>fiddle here
一些国家的人口是其任何邻国(同一大陆)人口的三倍多。给出国家和大洲。
From https://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial, question 10
我试过这个:
SELECT w.name, w.continent
FROM world w
WHERE w.population/3 > (SELECT min(w2.population)
FROM world w2
WHERE w2.continent = w.continent);
这个解决方案似乎有效:
SELECT w.name, w.continent
FROM world w
WHERE w.population > (SELECT 3 * MAX(w2.population)
FROM world w2
WHERE w2.continent = w.continent AND
w2.name <> w.name
);
我试图理解我的解决方案中的逻辑缺陷。
为什么使用 max()
而不是 min()
,因为我们要比较人口是否是非洲大陆人口最少国家的 3 倍?
min/max 场景中是否需要 w2.name <> w.name
。为什么?
more than three times that of any of their neighbours
也就是说,同一个大陆上人口第二多的国家必须少于三分之一,而且每个大陆只有一个国家有资格。 (大陆上的最低人口数不相关。)
第二个查询获取同一大陆上除外部查询 (w2.name <> w.name
) 之外的所有国家/地区,找到人口最多的国家并乘以 3。如果仍然低于该国家/地区的人口外部查询,它通过了条件。
除此之外,虽然优雅 SQL,但查询开销很大,因为 相关子查询 必须计算一次每一行。这个应该更便宜:
SELECT *
FROM (
SELECT DISTINCT ON (continent)
name, continent, population
, lead(population) OVER (PARTITION BY continent ORDER BY population DESC) AS next_population
FROM world
ORDER BY continent, population DESC
) sub
WHERE population > 3 * next_population;
db<>fiddle here