子查询单独使用时会产生不同的结果

时间:2018-10-28 11:45:37

标签: sql postgresql

我必须跨两个不同的表countrycity编写查询。目标是获得每个地区以及每个国家/地区的人口。由于地区只是每个城市的属性,因此我必须将每个城市的所有人口都归入一个地区。

到目前为止,我的查询如下:

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

加入时该缩写显然改变了

我希望有人能对此有所启发。

1 个答案:

答案 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
;