Question

For example purposes lets say Im trying to figure out the average score for males and females from each parent.

Example data looks like this:

parentID    childID    sex    score
------------------------------------
1           21         m      17
1           23         f      12
2           33         f      55
2           55         m      22 
3           67         m      26
3           78         f      29
3           93         m      31

This is the result I want:

parentID    offspring   m    f   avg-m  avg-f  avg-both
----------------------------------------------------
1           2           1    1   17     12     14.5 
2           2           1    1   22     55     38.5
3           3           2    1   28.5   29     28.67

With the below query I can find the average for both males and females but I'm not sure how to get the average for either male or female

SELECT parentID, COUNT( childID ) AS offspring, SUM( IF( sex =  'm', 1, 0 ) ) AS m, SUM( IF( sex =  'f', 1, 0 ) ) AS f, max(score) as avg-both
FROM sexb_1
WHERE avg-both > 11
GROUP BY parentID

I tried something like this in the query but it returns an error

AVG(IF(sex = 'm', max(score),0)) as avg-m
Was it helpful?

Solution

I tried something like this in the query but it returns an error

AVG(IF(sex = 'm', max(score),0)) as avg-m

You can't use one aggregate function within another (in this case, MAX() within AVG())—what would that even mean? Once one has discovered the MAX() of the group, over what is there to take an average?

Instead, you want to take the AVG() of score values where the sex matches your requirement; since AVG() ignores NULL values and the default for unmatched CASE expressions is NULL, one can simply do:

SELECT   parentID, 
         COUNT(*) offspring,
         SUM(sex='m') m,
         SUM(sex='f') f,
         AVG(CASE sex WHEN 'm' THEN score END) `avg-m`,
         AVG(CASE sex WHEN 'f' THEN score END) `avg-f`,
         AVG(score) `avg-both`
FROM     sexb_1
GROUP BY parentID
HAVING   `avg-both` > 11

See it on sqlfiddle.

OTHER TIPS

Using if

SELECT parentID, COUNT( childID ) AS offspring, 
      SUM(iF( sex='m', 1 ,0 )) AS m, 
      SUM(iF( sex='f', 1 ,0 )) AS f,
      AVG(if(sex='m', score, null)) as avg_m,
      AVG(if(sex='f', score, null)) as avg_f,
      AVG(score) as avgboth
FROM     sexb_1
GROUP BY parentID
HAVING   avgboth > 11

fiddle

  • In your query the error is due to the usage of avg-both You need to use back ticks or underscore for the alias name. Here it considers it as difference of avg and both
  • And also you cannot use alias names inside where clause as after the table name is picked up from the query, it is the where clause that comes next. So the database doesn't know the alias names yet.

You can try below query-

    SELECT 
    parentID, COUNT(childID) AS `offspring`,
     COUNT(IF(sex = 'm',sex ,NULL )) AS `m`, COUNT(IF(sex = 'f', sex,NULL)) AS `f`,
     AVG(IF(sex = 'm',score,NULL )) AS `avg-m`, COUNT(IF(sex = 'f', score,NULL)) AS `avg-f`, 
AVG(score) AS `avg-both` 
    FROM sexb_1 
    GROUP BY parentID 
    HAVING `avg-both` > 11;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top