MySQL how to get avg of values into specific range

北慕城南 提交于 2020-12-09 06:43:49

问题


I have the following table data:

value
1
5
10.5
12
36

I want to map these values into:

range      avg
0-21       (1 + 5 + 10.5 + 12) / 4
21.001-34  0
34.001-64  36
64 +       0

Basically map each value to ranges and calculate the avg of all values in each range.

I tried to do:

select 
case
when avggeneral between 0 and 21 then ' 0-21'
when avggeneral between 21.00001 and 34 then ' 21-34'
when avggeneral between 34.00001 and 64 then ' 34-64'
else '64+'
end as 'range',
AVG(*) as 'avg'
from table

but this doesn't work... I don't know how to make the static ranges...

How can I do that in MySQL?

Methology should be: 1. Map values into these groups ( 0-21, 21-34 etc..) 2. calulate AVG in each group.

Desired output for above example is this:

range      avg
0-21       7.125
21.001-34  0
34.001-64  36
64 +       0

The range column is static. Always with 5 rows. The avg column is dynamic.. the values there are the actual AVGs of value column.


回答1:


You could build a list of ranges using UNION ALL and LEFT JOIN with it:

SELECT CONCAT(IFNULL(ranges.min, '∞'), '-', IFNULL(ranges.max, '∞')) AS `range`, avg(value) AS avg
FROM (
    SELECT 0 AS min, 21 AS max UNION ALL
    SELECT 21, 34 UNION ALL
    SELECT 34, 64 UNION ALL
    SELECT 64, NULL
) AS ranges
LEFT JOIN t ON (ranges.min IS NULL OR value >= ranges.min) AND
               (ranges.max IS NULL OR value <  ranges.max)
GROUP BY ranges.min, ranges.max

Note that the above query will put 20.9999 inside [0-21) and 21.0000 inside [21-34) range.




回答2:


You can use UNION to get the desired result like below :

select '0-21' as Range1, coalesce(avg(avggeneral),0) as AVG from Table1
where avggeneral > 0 and avggeneral <= 21
union
select '21-34' as Range1, coalesce(avg(avggeneral),0) as AVG from Table1
where avggeneral > 21 and avggeneral <= 34
union
select '34-64' as Range1, coalesce(avg(avggeneral),0) as AVG from Table1
where avggeneral > 34 and avggeneral <= 64
union
select '64+' as Range1, coalesce(avg(avggeneral),0) as AVG from Table1
where avggeneral > 64

SQL HERE




回答3:


You don't really need to use those decimals.
Because for example, if the "value" equals 21, then the CASE would already return the 0-21 range before evaluating the next WHEN.

But you still need to group on the range.

And to return all the ranges, whether or not they are missing, you could left join to a sub-query with the ranges.

SELECT Ranges.`range`, COALESCE(AVG(Q.`value`), 0) as `avg`
FROM
(
  SELECT 0 as `class`, ' 0-21' as `range`
  UNION ALL SELECT 21, '21-34'
  UNION ALL SELECT 34, '34-64'
  UNION ALL SELECT 64, '64+'
) Ranges
LEFT JOIN
(
  SELECT 
   `value`,
   case
   when `value` between  0 and 21 then 0
   when `value` between 21 and 34 then 21
   when `value` between 34 and 64 then 34
   when `value` > 64 then 64
   end as rangeclass
  FROM test
) Q ON Q.rangeclass = Ranges.`class`
GROUP BY Ranges.`class`, Ranges.`range`
ORDER BY Ranges.`class`

db<>fiddle here



来源:https://stackoverflow.com/questions/53593388/mysql-how-to-get-avg-of-values-into-specific-range

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!