我必须跨两个不同的表country
和city
编写查询。目标是获得每个地区以及每个国家/地区的人口。由于地区只是每个城市的属性,因此我必须将每个城市的所有人口都归入一个地区。
到目前为止,我的查询如下:
SELECT country.name, country.population, array_agg(
(SELECT (c.district, sum(city.population))
FROM city GROUP BY c.district))
AS districts
FROM country
FULL OUTER JOIN city c ON country.code = c.countrycode
GROUP BY country.name, country.population;
结果:
name | population | districts
---------------------------------------------+------------+------------------------------------------------------------------------------------------------------------------
Afghanistan | 22720000 | {"(Balkh,1429559884)","(Qandahar,1429559884)","(Herat,1429559884)","(Kabol,1429559884)"}
Albania | 3401200 | {"(Tirana,1429559884)"}
Algeria | 31471000 | {"(Blida,1429559884)","(Béjaïa,1429559884)","(Annaba,1429559884)","(Batna,1429559884)","(Mostaganem,1429559884)"
American Samoa | 68000 | {"(Tutuila,1429559884)","(Tutuila,1429559884)"}
因此,显然,它汇总了世界上所有城市的人口。我需要以某种方式将其限制在每个地区。
但是如果我单独运行子查询
SELECT (city.district, sum(city.population)) FROM city GROUP BY city.district;
它给了我这些地区及其人口:
row
----------------------------------
(Bali,435000)
(,4207443)
(Dnjestria,194300)
(Mérida,224887)
(Kochi,324710)
(Qazvin,291117)
(Izmir,2130359)
(Meta,273140)
(Saint-Denis,131480)
(Manitoba,618477)
(Changhwa,354117)
我意识到它必须使用加入时的缩写来做一些事情。我使用它是为了方便,但它似乎有实际的后果,因为如果我不使用它,它将给我错误
more than one row returned by a subquery used as an expression
此外,如果我使用
sum(c.population)
在子查询中它不会执行,因为
aggregate function calls cannot be nested
加入时该缩写显然改变了 。
我希望有人能对此有所启发。
答案 0 :(得分:0)
我自己解决了。
窗口函数是执行此类任务的最便捷方法:
SELECT DISTINCT
country.name
, country.population
, city.district
, sum(city.population) OVER (PARTITION BY city.district)
AS district_population
, sum(city.population) OVER (PARTITION BY city.district)/ CAST(country.population as float)
AS district_share
FROM
country JOIN city ON country.code = city.countrycode
;
但它也适用于子选择:
SELECT DISTINCT
country.name
, country.population
, city.district
,(
SELECT
sum(ci.population)
FROM
city ci
WHERE ci.district = city.district
) AS district_population
,(
SELECT
sum(ci2.population)/ CAST(country.population as float)
FROM
city ci2
WHERE ci2.district = city.district
) AS district_share
FROM
country JOIN city ON country.code = city.countrycode
ORDER BY
country.name
, country.population
;