简体   繁体   中英

Subquery yields different results when used alone

I have to write a query across two different tables country and city . The goal is to get every district and that district's population for every country. As the district is just an attribute of each city, I have to subsume all the populations of every city belonging to a district.

My query so far looks like this:

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;

The result:

                    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)"}

So apparently it sums all the city-populations of the world. I need to limit that somehow to each district alone.

But if I run the Subquery alone as

SELECT (city.district, sum(city.population)) FROM city GROUP BY city.district;

it gives me the districts with their population:

               row                
----------------------------------
(Bali,435000)
(,4207443)
(Dnjestria,194300)
(Mérida,224887)
(Kochi,324710)
(Qazvin,291117)
(Izmir,2130359)
(Meta,273140)
(Saint-Denis,131480)
(Manitoba,618477)
(Changhwa,354117)

I realized it has to do something with the abbreviation that I use when joining. I used it for convenience but it seems to have real consequences because if I don't use it, it gives me the error

more than one row returned by a subquery used as an expression

Also, if I use

sum(c.population)

in the subquery it won't execute because

aggregate function calls cannot be nested

This abbreviation when joining apparently changes a lot .

I hope someone can shed some light on that.

Solved it myself.

Window functions are the most convenient method for this kind of task:

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
;

But it also works with subselects:

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
;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM