sql >> Base de Datos >  >> RDS >> Mysql

Calcular el percentil de la frecuencia en MySQL

A veces, es posible que desee calcular el percentil a partir de la frecuencia o los recuentos en MySQL en función de. Por ejemplo, para clasificar a los clientes según el número de compras o pedidos en lugar de las ventas totales. Todavía no hay funciones para ello. Aquí hay una consulta preparada para hacerlo.

Por ejemplo, tiene una tabla pedidos que contiene todos los pedidos de productos para cada usuario. Desea calcular el percentil a partir de la frecuencia de los pedidos.

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     |
+-----------+----------+---------+---------------+

Aquí hay una consulta que puede usar para calcular el percentil de la frecuencia o contar en MySQL. Simplemente reemplace las columnas:ID de usuario, ventas y tabla:orden. Cuenta el número de pedidos de cada usuario. Luego los clasifica según el número de pedidos. Finalmente, calcula el percentil usando el rango.

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 ya tiene una cantidad de pedidos para cada usuario en la tabla y desea usar la tabla directamente para calcular el percentil a partir de la frecuencia o el conteo, aquí tiene una consulta

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     |
+-----------+----------+---------+---------------+

Como puede ver, el último usuario clasificado no tiene un percentil cero. Esta es la naturaleza del cálculo de percentiles. La primera persona puede tener un percentil 100 o la última clasificada puede tener cero. Ambos no pueden ocurrir al mismo tiempo. Si desea forzar a la última persona clasificada a tener un percentil cero, puede usar las siguientes consultas. No estoy agregando 1 al rango al calcular el percentil.

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 ya tiene las ventas totales de cada usuario en la tabla y desea usar directamente la tabla para calcular el percentil, aquí tiene una consulta

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 para crear el orden de la tabla de muestra: