MySQL, как получить средние значения в определенном диапазоне - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть следующие данные таблицы:

value
1
5
10.5
12
36

Я хочу отобразить эти значения в:

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

По сути, сопоставить каждое значение с диапазонами и рассчитать среднее значение всех значений вкаждый диапазон.

Я пытался сделать:

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

, но это не работает ... Я не знаю, как сделать статические диапазоны ...

Как я могу это сделать в MySQL?

Метология должна быть: 1. Отображать значения в эти группы (0-21, 21-34 и т. Д.) 2. Вычислять AVG в каждой группе.

Желаемый вывод для приведенного выше примера:

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

Столбец range является статическим.Всегда с 5 рядами.Столбец avg является динамическим. Значения - это фактические значения AVG для столбца value.

Ответы [ 3 ]

0 голосов
/ 03 декабря 2018

На самом деле вам не нужно использовать эти десятичные дроби.
Потому что, например, если "значение" равно 21, то CASE уже вернет диапазон 0-21 до оценки следующего WHEN.

Но вам все равно нужно сгруппировать по диапазону.

И чтобы вернуть все диапазоны, независимо от того, отсутствуют они или нет, вы можете оставить присоединение к подзапросу с диапазонами.

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`

дБ <> скрипка здесь

0 голосов
/ 03 декабря 2018

Вы можете использовать UNION для получения желаемого результата, как показано ниже:

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

0 голосов
/ 03 декабря 2018

Вы можете построить список диапазонов, используя UNION ALL и LEFT JOIN с ним:

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

Обратите внимание, что вышеупомянутый запрос поместит 20.9999 внутри [0-21) и 21.0000 внутри *Диапазон 1009 *.

...