Vous pouvez calculer la médiane avec GROUP BY dans MySQL même s'il n'y a pas de fonction médiane intégrée.
Considérez le tableau :
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
Pour chaque ligne, vous pouvez compter le nombre d'éléments similaires qui sont inférieurs. Vous pouvez également compter le nombre de valeurs inférieures ou égales :
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
Avec requête
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
La valeur médiane se produit lorsque le nombre inférieur ou égal est égal à la moitié du nombre d'éléments
-
Acrington a 4 articles. La moitié de ceci est 2 qui est dans la gamme 0..2 (correspondant à 200.00) et aussi dans la gamme 2..3 (correspondant à 300.00)
-
Bullingdon a aussi 4 articles. 2 est compris entre 1..2 (valeur 300.00) et 2..3 (valeur 400.00)
-
Cardington a 5 articles. La valeur 2.5 est comprise entre 2 et 3 ce qui correspond à Cardington 151.
La valeur médiane est la moyenne des valeurs min et max renvoyées par :
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
Ce qui donne :
Acrington 200.00
Acrington 200.00
Acrington 300.00
Bulingdon 300.00
Bulingdon 400.00
Cardington 151.00
Enfin, nous pouvons obtenir la médiane :
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
Donner
Acrington 250.000000
Bulingdon 350.000000
Cardington 151.000000