Mysql
 sql >> Base de données >  >> RDS >> Mysql

Calculer le centile à partir de la fréquence dans MySQL

Parfois, vous voudrez peut-être calculer le centile à partir de la fréquence ou du nombre dans MySQL en fonction de. Par exemple, pour classer les clients en fonction du nombre d'achats ou de commandes au lieu du total des ventes. Il n'y a pas encore de fonctions pour cela. Voici une requête toute faite pour le faire.

Par exemple, vous avez une table commandes qui contient toutes les commandes de produits pour chaque utilisateur. Vous souhaitez calculer le centile à partir de la fréquence des commandes.

order
+------+--------------+-------------+
|  user_id  |   product  |   sales  |
+-----------+------------+----------+
|     1     |     Soap   |    10    |
|     4     |   Perfume  |   100    |
|     1     |   Noodles  |   20     |
|     4     |     Soap   |   10     |
|     1     |    Glue    |   20     |
|     3     |     Deo    |   200    |
+-----------+------------+----------+
percentiles
+-----------+----------+---------+---------------+
|  user_id  |   total  |  rank   |   percentile  |
+-----------+----------+---------+---------------+
|     1     |     3    |    1    |      100      |
|     4     |     2    |    2    |     66.67     |
|     3     |     1    |    3    |     33.33     |
+-----------+----------+---------+---------------+

Voici une requête que vous pouvez utiliser pour calculer le centile à partir de la fréquence ou du nombre dans MySQL. Remplacez simplement les colonnes - user_id, sales et table - order. Il compte le nombre de commandes pour chaque utilisateur. Ensuite, il les classe sur le nombre de commandes. Enfin, il calcule le centile à l'aide du rang.

select user_id,total,rank,round(100*(cnt-rank+1)/cnt,0) as percentile from   
(SELECT  user_id,total,@curRank := @curRank + 1 AS rank
FROM      (select user_id,count(sales) as total from `order` group by user_id)
p, (SELECT @curRank := 0) r
ORDER BY  total desc ) as dt,(select count(distinct user_id) as cnt from
`order`) as ct

Si vous avez déjà un nombre de commandes pour chaque utilisateur dans le tableau et que vous souhaitez utiliser directement le tableau pour calculer le centile à partir de la fréquence ou du nombre, voici une requête

select user_id,total,rank,round(100*(cnt-rank+1)/cnt,0) as percentile from   
(SELECT  user_id,total,@curRank := @curRank + 1 AS rank
FROM   `order`
p, (SELECT @curRank := 0) r
ORDER BY  total desc ) as dt,(select count(distinct user_id) as cnt from
`order`) as ct
order
+-----------+----------+
|  user_id  |   total  |
+-----------+----------+
|     1     |    3     |
|     4     |    2     |
|     3     |    1     |
+-----------+----------+
percentiles
+-----------+----------+---------+---------------+
|  user_id  |   total  |  rank   |   percentile  |
+-----------+----------+---------+---------------+
|     1     |     3    |    1    |      100      |
|     4     |     2    |    2    |     66.67     |
|     3     |     1    |    3    |     33.33     |
+-----------+----------+---------+---------------+

Comme vous pouvez le voir, le dernier utilisateur classé n'a pas de centile zéro. C'est la nature du calcul du centile. Soit la première personne peut avoir 100 centiles, soit la dernière classée peut avoir zéro. Les deux ne peuvent pas arriver en même temps. Si vous souhaitez forcer la dernière personne classée à avoir un centile zéro, vous pouvez utiliser les requêtes suivantes. Je n'ajoute pas 1 au rang lors du calcul du centile.

select user_id,total,rank,round(100*(cnt-rank)/cnt,0) as percentile from   
(SELECT  user_id,total,@curRank := @curRank + 1 AS rank
FROM      (select user_id,count(sales) as total from `order` group by user_id)
p, (SELECT @curRank := 0) r
ORDER BY  total desc ) as dt,(select count(distinct user_id) as cnt from
`order`) as ct

Si vous avez déjà le total des ventes pour chaque utilisateur dans le tableau et que vous souhaitez utiliser directement le tableau pour calculer le centile, voici une requête

select user_id,total,rank,round(100*(cnt-rank)/cnt,0) as percentile from   
(SELECT  user_id,total,@curRank := @curRank + 1 AS rank
FROM   `order`
p, (SELECT @curRank := 0) r
ORDER BY  total desc ) as dt,(select count(distinct user_id) as cnt from
`order`) as ct
percentiles
+-----------+----------+---------+---------------+
|  user_id  |   total  |  rank   |   percentile  |
+-----------+----------+---------+---------------+
|     1     |    3     |    1    |     66.67     |
|     4     |    2     |    2    |     33.33     |
|     3     |    1     |    3    |       0       |
+-----------+----------+---------+---------------+

SQL pour créer l'exemple d'ordre de table :