简体   繁体   中英

MySQL Sum, Count or Join?

I have the following MySQL query:

SELECT 
Country, City, 
COUNT(City) As Total, 
SUM(completion_status IN ('Started', 'Complete')) AS Total_Resp
FROM trespondent 
WHERE completion_status <> 'New' 
GROUP BY Country, City 
ORDER BY Counntry, City

This brings back what I would expect, which is a list of Cities with the Counts in each, no problem at all

Country     City     Total     Total_Resp
UK          London   150       23
UK          Leeds    150       83
France      Paris    235       99
France      Lyon     421       222

What I am trying to do is bring back the Total for the Countries as a whole as well, so UK and France as a whole would look like this:

Country     City     Total_Country   Total_city   Total_Resp
UK          London   300                150       23
UK          Leeds    300                150       83
France      Paris    656                235       99
France      Lyon     656                421       222

Now, I've tried simply adding to the SQL statement

COUNT(Country) As Total_Country
SUM(Country) As Total_Country

But both bring back the same count as City, I'm now thinking this is not possible without the use of JOIN. Can anyone advise?

Thanks in advance.

You can use a correlated subquery for this:

SELECT t1.Country, t1.City, 
       (SELECT COUNT(t2.Country)
        FROM trespondent AS t2
        WHERE t2.Country = t1.Country) AS Total_Country,
        COUNT(t1.City) As Total_city, 
       SUM(t1.completion_status IN ('Started', 'Complete')) AS Total_Resp
FROM trespondent AS t1
WHERE t1.completion_status <> 'New' 
GROUP BY t1.Country, t1.City 
ORDER BY t1.Country, t1.City

In most databases, you would just use window functions. In MySQL, there are several approaches.

SELECT r.Country, r.City, rr.Total_Country, COUNT(r.City) As Total, 
       SUM(r.completion_status IN ('Started', 'Complete')) AS Total_Resp
FROM trespondent r JOIN
     (SELECT r2.Country, COUNT(*) as Total_Country
      FROM trespondent r2
      WHERE r2.completion_status <> 'New' 
      GROUP BY r2.Country
     ) rr
     ON r.Country = rr.Country
WHERE r.completion_status <> 'New' 
GROUP BY r.Country, r.City, rr.Total_Country
ORDER BY r.Country, r.City;

Although you can approach this in other ways (such as a correlated subquery), I suspect you might want other values summarized at the country level as well. These are easier to add with a subquery. For instance, you can readily add the number of responders in the country as well.

You can use CASE . For example:

SELECT COUNT(*) AS total, SUM(CASE WHEN Country = 'France' THEN 1 ELSE 0 END) AS totalFrance

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