7
votes

Calculer la médiane avec mysql

J'ai du mal à calculer la médiane d'une liste de valeurs, pas la moyenne.

J'ai trouvé cet article moyen simple de calculer la médiane avec MySQL

Il a une référence à la requête suivante que je ne comprends pas correctement. xxx

si j'ai une colonne et je veux calculer la valeur médiane, qu'est-ce que le x et < Code> y colonnes se réfèrent à?


2 commentaires

Notez que la solution que vous avez mentionnée ne trouvera pas la médiane s'il ya des valeurs dupliquées. (Il échoue lorsque la médiane elle-même a des duplicats)


Honnêtement, je ne comprends honnêtement comment MySQL est utilisé par des millions de personnes et travaillé depuis des décennies mais n'a pas de fonction pour calculer une médiane. Existe-t-il d'autres systèmes centrés sur les données qui n'ont pas mis en œuvre des mathématiques qui sont généralement enseignées à 9-10 ans en 4e année?


7 Réponses :


2
votes

val est votre colonne de temps, x et y sont deux références à la table de données (vous pouvez écrire des données comme x x , Data comme Y ).

Edit: Pour éviter de calculer vos sommes deux fois, vous pouvez stocker les résultats intermédiaires. xxx

alors vous pouvez calculer la médiane sur ces valeurs qui sont dans une table nommée.

EDIT: Table temporaire ne fonctionnera pas ici. Vous pouvez essayer d'utiliser une table régulière avec du type de table "mémoire". Ou simplement avoir votre sous-requête qui calcule les valeurs pour la médiane deux fois dans votre requête. En dehors de cela, je ne vois pas une autre solution. Cela ne signifie pas qu'il n'y a pas de meilleure façon, peut-être que quelqu'un d'autre viendra avec une idée.


2 commentaires

Merci pour ça @krab! Ne supposez pas que vous puissiez m'aider avec ce qui suit. Sélectionnez AVG (Time_Takaken) à partir de (Sélectionnez SUM ( TIME ) en tant que scores sur les scores où créé_at> = '2010-10-10' et créé_at <= '2010-11-11' groupe par user_id) moyenne_user_total_time ") Pour calculer la moyenne des résultats totaux des utilisateurs, mais je ne sais pas comment appliquer la formule médiane à cette requête. Désolé pour le nouveau post, a expiré.


Quand j'essaie ça, je reçois "ne peut pas rouvrir la table x". Voici mon SQL total. Créer une table temporaire moyenne_user_total_time (Sélectionnez la somme (heure) comme time_taken à partir de scores où créé_at> = '2010-10-10' et créé_at <= '2010-11-11' GROUPE par user_id); Sélectionnez X.Time_Takaken à partir de moyenne_user_total_time sous x, moyenne_user_total_time comme groupe Y par x.time_taken ayant une somme (signe (1-signe (Y.time_taken-x.time_taken))) = (Nombre (*) + 1) / 2



1
votes

Essayez d'abord de comprendre ce que la médiane est: c'est la valeur moyenne dans la liste triée des valeurs.

Une fois que vous avez compris cela, l'approche est deux étapes:

  1. Trier les valeurs dans l'un ou l'autre ordre
  2. Choisissez la valeur moyenne (sinon un nombre impair de valeurs, choisissez la moyenne des deux valeurs moyennes)

    Exemple: xxx

    Donc, pour trier les dates, vous avez besoin d'une valeur numérique; Vous pouvez obtenir leur horodatage (comme des secondes écoulées de l'époque) et utiliser la définition de médiane.


2 commentaires

pas d'accord sur votre premier exemple: Médian est toujours un membre réel de l'ensemble


@zanlok: tout logiciel "bien accepté" calculera la médiane comme je l'ai présentée (valeur moyenne si nombre de valeurs) Matlab moyennes, les moyennes r. Ce dont vous parlez est le "Medoid", où la valeur est toujours membre du jeu de données.



11
votes

Je propose une voie plus rapide.

Obtenez le nombre de lignes:

Sélectionnez CEIL (COUNT (*) / 2) des données;

puis prenez la valeur moyenne dans une sous-requête triée:

Sélectionnez max (VAL) à partir de (Sélectionnez VAL de la commande de données par VAL LIMIT @MIDDLEVALUE) X;

J'ai testé cela avec un ensemble de données 5x10E6 de nombres aléatoires et il trouvera la médiane en moins de 10 secondes.

Ceci trouvera un centile arbitraire en remplaçant le Nombre (*) / 2 avec Nombre (*) * N n est le centile (.5 pour la médiane, .75 pour le 75e centile, etc.).


1 commentaires

Bonne solution, mais s'il y a un nombre impair d'éléments, vous devez probablement obtenir la moyenne des deux points de médiane Sélectionnez AVG (VAL) à partir de (Sélectionnez VAL de la commande de données par VAL LIMIT @MIDDLEVALUE, @NumValues) x; Où @numvalues ​​est (@ MiddleValue Mod 2) +1



1
votes

Recherche médiane dans mysql à l'aide de groupe_concat

Query: xxx

Explication: < p> Le tri est effectué à l'aide de la commande à l'intérieur de la fonction GROUP_CONCAT

Position (POS) et le nombre total d'éléments (compte) est identifié. Le plafond pour identifier la position nous aide à utiliser la fonction Substring_index dans les étapes ci-dessous.

basé sur le nombre, même ou un nombre impair de valeurs est décidé.

  • Valeurs impairs: choisissez directement l'élément appartenant à la POS à l'aide de Substring_index.
  • Valeurs même: Trouvez l'élément appartenant à la POS et à POS + 1, puis ajoutez-les et divisez par 2 pour obtenir la médiane.

    Enfin, la médiane est calculée.


0 commentaires

1
votes

Si vous avez une table R avec une colonne nommée A , et que vous voulez la médiane d'une , vous pouvez faire comme suit: xxx

note : Cela ne fonctionnera que s'il n'y a pas de valeurs dupliquées dans A. De plus, les valeurs NULL ne sont pas autorisées.


1 commentaires

@ Nicholas-de-bin Comment cela fonctionne-t-il quand il y a un nombre pair de rangées dans la colonne? Parce que la logique traditionnelle est destinée à des chiffres même que nous devons retourner la moyenne des deux nombres au milieu. Ceci n'est pas traité dans la requête ci-dessus. S'il vous plaît corrigez-moi si vous êtes faux.



1
votes

Moi les plus simples et mon ami a découvert ... Profitez !!

SELECT count(*) INTO @c from station;
select ROUND((@c+1)/2) into @final; 
SELECT round(lat_n,4) from station a where @final-1=(select count(lat_n) from station b where b.lat_n > a.lat_n);


0 commentaires

0
votes

Voici une solution facile à comprendre. Il suffit de remplacer votre_column fort> et votre_table forte> selon votre exigence.

SET @r = 0;

SELECT AVG(Your_Column)
FROM (SELECT (@r := @r + 1) AS r, Your_Column FROM Your_Table ORDER BY Your_Column) Temp
WHERE
    r = (SELECT CEIL(COUNT(*) / 2) FROM Your_Table) OR
    r = (SELECT FLOOR((COUNT(*) / 2) + 1) FROM Your_Table)


0 commentaires