简体   繁体   中英

How to reference multiple sums of a related table as a subquery

I have a table of data I need to pull out each row. This table ( A ) has a many-to-one relationship to another table B (many instances of A referenced in B .

I want to output each row of A with numerous SUM's of values of B ; I can think of doing this with Sub-Select's but they feel inefficient and a bit repetative.

There are 3 columns in B that need to be summed. I (feel I) can not JOIN these tables because sometimes A will not appear in B at all, and often A will appear multiple times.

What I've read:

Amongst other things;

I don't feel these have helped me due to various reasons; people suggest JOIN's but I don't think I can use JOINs due to having 0+ number of related rows. Also some answers are too specific to the questions so don't seem to help in my situation.

What I've Got:

Example Data, table creation:

    CREATE TABLE Countries (
    Id INT NOT NULL AUTO_INCREMENT,
    ISO VARCHAR(2) NOT NULL,
    ISO3 VARCHAR(3) NOT NULL,
    ISONumeric INT NOT NULL,
    CountryName VARCHAR(64) NOT NULL,
    Capital VARCHAR(64) NOT NULL,
    CurrencyCode VARCHAR(3) NOT NULL,
    PRIMARY KEY(Id)
);

CREATE TABLE Cities (
    cId INT NULL AUTO_INCREMENT,
    CityName VARCHAR(64) NOT NULL,
    Population INT(7) NOT NULL, 
    Natives INT(7) NOT NULL,
    Country TINYINT(3) NOT NULL,
    PRIMARY KEY(cId)
);

INSERT INTO Countries
    (ISO, ISO3, ISONumeric, CountryName, Capital, CurrencyCode)
VALUES
    ('AU', 'AUS', 36, 'Australia', 'Canberra',  'AUD'),
    ('DE', 'DEU', 276, 'Germany', 'Berlin',  'EUR'),
    ('GB', 'UKG', 1, 'Britain', 'London',  'GBP'),
    ('IN', 'IND', 356, 'India', 'New Delhi',  'INR'),
    ('LA', 'LAO', 418, 'Laos', 'Vientiane',  'LAK'),
    ('US', 'USA', 840, 'United States', 'Washington',  'USD'),
    ('ZW', 'ZWE', 716, 'Zimbabwe', 'Harare', 'ZWL')
;

INSERT INTO Cities
    (CityName, Population, Natives, Country)
VALUES
    ('London', 6431000, 1362434, 3),
    ('Sheffield', 136000, 1434, 3),
    ('Luton', 61000, 134, 3),
    ('Munich', 231000, 134214, 2),
    ('New York', 12131000, 16, 6),
    ('Washington', 210700, 343, 6)
;

Example Query generation:

SELECT Countries.*, 
(SELECT SUM(`Population`) FROM Cities WHERE `Country` = `Countries`.`Id` ) as pop,
(SELECT SUM(`Natives`) FROM Cities WHERE `Country` = `Countries`.`Id` ) as native
FROM Countries

This query works, but I have a perception it can easily become extremely cumbersome. It appears to be multipe SELECTs on the same table ( Cities ) (My examples shows two SUM selects but I will eventually have many more).

SQL Fiddle:

http://www.sqlfiddle.com/#!9/9d5d47/4

What's My Issue?

I want to easily be able to SUM(...) various columns of B relating to A to add as an output when dumping the contents of A . There may be zero or more occurances of A referenced in B .

How should I do this with more efficiency and less repetition than numerous Subqueries?

For example is it possible to combine all the SUM's into a single subquery?

If I guess correct, your query should be as below-

DEMO HERE

SELECT 
A.column_1,A.column_2,A.column_3,  -- LIST your required columns from table  Countries
SUM(B.Population) as pop,
SUM(B.Natives) as native
FROM Countries A
LEFT JOIN Cities B ON B.Country = A.Id 
GROUP BY A.column_1,A.column_2,A.column_3 -- GROUP BY with same columns in select list

You might find this easier by aggregating before joining:

SELECT co.*, ci.pop, ci.natives
FROM Countries co LEFT JOIN
     (SELECT ci.Country,
             SUM(ci.Population) as pop,
             SUM(ci.Natives) as native
      FROM Cities ci 
      GROUP BY ci.Country
     ) ci
     ON ci.Country = co.Id ;

This eliminates the need to repeat all the columns in the country table. If the JOIN keys are the same, you can simplify this to:

SELECT *
FROM Countries co LEFT JOIN
     (SELECT ci.Country as id,
             SUM(ci.Population) as pop,
             SUM(ci.Natives) as native
      FROM Cities ci 
      GROUP BY ci.Country
     ) ci
     USING (id);

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