一些 DDL 可以玩。
create table country (
country_code char(2) primary key, -- ISO country code
country_name varchar(35) not null unique
);
insert into country values
('US', 'United States of America'),
('IT', 'Italy'),
('IN', 'India');
-- The full name of a city is more than city name plus country name.
-- In the US, there are a couple of dozen cities named Springfield,
-- each in a different state. I'd be surprised if this weren't true
-- in most countries.
create table city (
country_code char(2) not null references country (country_code),
name varchar(35) not null,
population integer not null check (population > 0),
primary key (country_code, name)
);
insert into city values
('US', 'Rome, GA', 36303),
('US', 'Washington, DC', 632323),
('US', 'Springfield, VA', 30484),
('IT', 'Rome', 277979),
('IT', 'Milan', 1324110),
('IT', 'Bari', 320475),
('IN', 'Mumbai', 12478447),
('IN', 'Patna', 1683200),
('IN', 'Cuttack', 606007);
人口最多的国家。
select country.country_code, max(city.population) as max_population
from country
inner join city on country.country_code = city.country_code
group by country.country_code;
有几种方法可以使用它以获得您想要的结果。一种方法是在公用表表达式上使用内连接。
with max_population as (
select country.country_code, max(city.population) as max_population
from country
inner join city on country.country_code = city.country_code
group by country.country_code
)
select city.country_code, city.name, city.population
from city
inner join max_population
on max_population.country_code = city.country_code
and max_population.max_population = city.population;
另一种方法是在子查询上使用内连接。(公用表表达式的文本“进入”主查询。使用别名“max_population”,查询不需要进一步更改即可工作。)
select city.country_code, city.name, city.population
from city
inner join (select country.country_code, max(city.population) as max_population
from country
inner join city on country.country_code = city.country_code
group by country.country_code
) max_population
on max_population.country_code = city.country_code
and max_population.max_population = city.population;
还有一种方法是在子查询中使用窗口函数。您需要从子查询中进行选择,因为您不能在 WHERE 子句中直接使用 rank() 的结果。也就是说,这行得通。
select country_code, name, population
from (select country_code, name, population,
rank() over (partition by country_code
order by population desc) as city_population_rank
from city
) city_population_rankings
where city_population_rank = 1;
但事实并非如此,尽管乍一看它更有意义。
select country_code, name, population,
rank() over (partition by country_code
order by population desc) as city_population_rank
from city
where city_population_rank = 1;
ERROR: column "city_population_rank" does not exist