遊ぶためのいくつかの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;
必要な結果を得るために、それを使用する方法はいくつかあります。1 つの方法は、共通テーブル式で内部結合を使用することです。
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;
もう 1 つの方法は、サブクエリで内部結合を使用することです。(共通テーブル式のテキストは、メイン クエリに「入ります」。別名「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