Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Usando MEDIAN ao lado das funções MAX, MIN e AVG no MySQL


Você pode calcular a mediana com GROUP BY no MySQL mesmo que não haja uma função mediana incorporada.

Considere a tabela:
Acrington   200.00
Acrington   200.00
Acrington   300.00
Acrington   400.00
Bulingdon   200.00
Bulingdon   300.00
Bulingdon   400.00
Bulingdon   500.00
Cardington  100.00
Cardington  149.00
Cardington  151.00
Cardington  300.00
Cardington  300.00

Para cada linha, você pode contar o número de itens semelhantes que são menores. Você também pode contar quantos valores são menores ou iguais:
name        v       <   <=
Acrington   200.00  0   2
Acrington   200.00  0   2
Acrington   300.00  2   3
Acrington   400.00  3   4
Bulingdon   200.00  0   1
Bulingdon   300.00  1   2
Bulingdon   400.00  2   3
Bulingdon   500.00  3   4
Cardington  100.00  0   1
Cardington  149.00  1   2
Cardington  151.00  2   3
Cardington  300.00  3   5
Cardington  300.00  3   5

Com consulta
SELECT name,v, (SELECT COUNT(1) FROM sale WHERE v<o.v AND name=o.name) as ls
             , (SELECT COUNT(1) FROM sale WHERE v<=o.v AND name=o.name) as lse
  FROM sale o

O valor mediano ocorrerá quando a contagem menor ou igual for metade do número de itens

  • Acrington tem 4 itens. Metade disso é 2 que está na faixa 0..2 (correspondente a 200.00) e também na faixa 2..3 (correspondente a 300.00)

  • Bullingdon também tem 4 itens. 2 está no intervalo 1..2 (valor 300.00) e 2..3 (valor 400.00)

  • Cardington tem 5 itens. O valor 2,5 está entre 2 e 3, o que corresponde a Cardington 151.

O valor mediano é a média dos valores mínimo e máximo retornados por:
SELECT cs.name,v
   FROM
   (SELECT name,v, (SELECT COUNT(1) FROM sale WHERE v<o.v AND name=o.name) as ls
                 , (SELECT COUNT(1) FROM sale WHERE v<=o.v AND name=o.name) as lse
      FROM sale o) cs JOIN
   (SELECT name,COUNT(1)*.5 as cn
      FROM sale
      GROUP BY name) cc ON cs.name=cc.name
 WHERE cn between ls and lse

Que dá:
Acrington   200.00
Acrington   200.00
Acrington   300.00
Bulingdon   300.00
Bulingdon   400.00
Cardington  151.00

Finalmente podemos obter a mediana:
SELECT name,(MAX(v)+MIN(v))/2 FROM
(SELECT cs.name,v
   FROM
   (SELECT name,v, (SELECT COUNT(1) FROM sale WHERE v<o.v AND name=o.name) as ls
                 , (SELECT COUNT(1) FROM sale WHERE v<=o.v AND name=o.name) as lse
      FROM sale o) cs JOIN
   (SELECT name,COUNT(1)*.5 as cn
      FROM sale
     GROUP BY name) cc ON cs.name=cc.name
 WHERE cn between ls and lse
 ) AS medians
GROUP BY name

Dando
Acrington   250.000000
Bulingdon   350.000000
Cardington  151.000000