简体   繁体   中英

mysql COUNT function on two or more columns as per true column value

I am trying to count the number of times the two columns have their assigned value appears. The sql statement I have so far outputs wrong results. Take a look:

SELECT 
    UPPER(school.district) AS District_name, 
    COUNT(DISTINCT task1.wp_status) AS Status_New, 
    COUNT(task1.wp_type) AS Type_Bolehole 
FROM school 
RIGHT OUTER JOIN task1 ON school.s_name=task1.name 
WHERE task1.wp_status="New" OR task1.wp_type="Bolehole" 
GROUP BY district AND task1.wp_status="New" AND task1.wp_type="Bolehole" 
ORDER BY district;

The two tables am using are as below

School

s_name         district
matero          lusaka
kema            lusaka 
naka            kabwe

task1

name     wp_status   wp_type
matero     New      Bolehole                       
kema       New      Bolehole                    
naka       New    ProtectedWell

expected output

D_Name Status_New Type_Bolehole         
KABWE       1       2
LUSAKA      2       0   

I would recommend writing the query like this:

SELECT UPPER(s.district) AS District_name, 
       SUM(t1.wp_status = 'New') AS Status_New, 
       SUM(t1.wp_type = 'Bolehole') AS Type_Bolehole 
FROM school s JOIN
     task1 t1
     ON s.s_name = t1.name 
WHERE t1.wp_status = 'New' or t1.wp_type = 'Bolehole'
GROUP BY UPPER(s.district)
ORDER BY District_Name;

This makes the following changes:

  • Table aliases are introduced to make the query easier to read and write.
  • The join is changed to an inner join . You are selecting on one table and aggregating by the other, so it seems that the query expects a match in both tables.
  • The group by is based on the actual expression used in the select .
  • Conditional aggregation is used to get the two columns of counts.

Note: This assumes that the sample results in the question are not correct.

you dont need a right join.. all you need is one conditional sum of the rows

SELECT
    UPPER(s.district) AS District_name,
    SUM(case when t.wp_status = 'New' then 1 else 0 end) AS Status_New,, 
    SUM(case when t.wp_type = 'Bolehole' then 1 else 0 end) AS Type_Bolehole 
FROM school s
LEFT JOIN task1 t ON s.s_name=t.name 
WHERE t.wp_status = 'New' or t.wp_type = 'Bolehole'
GROUP BY District_name
ORDER BY District_name;

DEMO

Try this

SELECT UPPER(school.district) AS District_name,
sum( task1.wp_status ="New") AS Status_New, 
sum(task1.wp_type="Bolehole") AS Type_Bolehole FROM school 
RIGHT OUTER JOIN task1 ON school.s_name=task1.name 
WHERE task1.wp_status="New" OR task1.wp_type="Bolehole" 
GROUP BY district  
ORDER BY district;

Also in your expected result set bolehole count for firt row should be 0 because task naka don't have type of bolehole

Fiddle Demo

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