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