百分位数(percentile)的详细定义见百度百科。

在这里我用一个通俗的例子来补充解释, 例如今年有900万人参加了高考,自然有900万个成绩,某个学校计划择优招生分数最高的前900个,那么分数线应该是多少呢,这就涉及到百分位的计算,这个学校录取的百分比就是万分之一,分数线的位置在万分之九千九百九十九,化成百分比就是99.99%,那对应这个百分比位置的具体数值是多少呢,这个说的就是百分位(percentile)。

Mysql中要实现根据若干条记录的某个字段获取指定百分位的值,用常规的自定义函数似乎行不通。我们用C/C++语言写一个mysql插件。

udf_percentile.cc, 这是插件的源代码。

/*

returns the percentile of the values in a distribution

input parameters:

data (real or int)

desired percentile of result, 0-1 (double)

decimals of output (optional, int)

output:

percentile value of the distribution (real)

compiling

gcc -fPIC -Wall -I /usr/include/mysql51/mysql/ -shared -o udf_percentile.so udf_percentile.cc

udf_percentile.so /usr/lib64/mysql/plugin/

registering the function:

CREATE AGGREGATE FUNCTION percentile RETURNS REAL SONAME 'udf_percentile.so';

getting rid of the function:

DROP FUNCTION percentile;

hat tip to Jan Steemann's udf_median function http://mysql-udf.sourceforge.net/

*/

#ifdef STANDARD

#include

#include

#include

#ifdef __WIN__

typedef unsigned __int64 ulonglong;

typedef __int64 longlong;

#else

typedef unsigned long long ulonglong;

typedef long long longlong;

#endif /*__WIN__*/

#else

#include

#include

#endif

#include

#include

#include

#ifdef HAVE_DLOPEN

#define BUFFERSIZE 1024

extern "C" {

my_bool percentile_init( UDF_INIT* initid, UDF_ARGS* args, char* message );

void percentile_deinit( UDF_INIT* initid );

void percentile_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );

void percentile_clear(UDF_INIT* initid, char *is_null, char *error);

void percentile_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );

double percentile( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );

}

struct percentile_data

{

unsigned long count;

unsigned long abscount;

unsigned long pages;

double *values;

};

my_bool percentile_init( UDF_INIT* initid, UDF_ARGS* args, char* message )

{

if ( args->arg_count < 2 || args->arg_count>3)

{

strcpy(message,"wrong number of arguments: percentile() requires two - three arguments");

return 1;

}

if (args->arg_type[0]!=REAL_RESULT && args->arg_type[0]!=INT_RESULT)

{

strcpy(message,"percentile() requires a real or int as parameter 1");

return 1;

}

if (args->arg_type[1]!=REAL_RESULT && args->arg_type[1]!=INT_RESULT && args->arg_type[1]!=DECIMAL_RESULT)

{

asprintf(&message,"percentile() requires a real/int as parameter 2, instead %d",args->arg_type[1]);

return 1;

}

if (args->arg_count>2 && args->arg_type[2]!=INT_RESULT)

{

strcpy(message,"percentile() requires an int as parameter 3");

return 1;

}

initid->decimals=2;

if (args->arg_count==3 && (*((ulong*)args->args[2])<=16))

{

initid->decimals=*((ulong*)args->args[2]);

}

percentile_data *buffer = new percentile_data;

buffer->count = 0;

buffer->abscount=0;

buffer->pages = 1;

buffer->values = NULL;

initid->maybe_null = 1;

initid->max_length = 32;

initid->ptr = (char*)buffer;

return 0;

}

void percentile_deinit( UDF_INIT* initid )

{

percentile_data *buffer = (percentile_data*)initid->ptr;

if (buffer->values != NULL)

{

free(buffer->values);

buffer->values=NULL;

}

delete initid->ptr;

}

void percentile_clear(UDF_INIT* initid, char *is_null, char *error){

percentile_data *buffer = (percentile_data*)initid->ptr;

buffer->count = 0;

buffer->abscount=0;

buffer->pages = 1;

*is_null = 0;

*error = 0;

if (buffer->values != NULL)

{

free(buffer->values);

buffer->values=NULL;

}

buffer->values=(double *) malloc(BUFFERSIZE*sizeof(double));

}

void percentile_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )

{

percentile_clear(initid, is_null, is_error);

percentile_add( initid, args, is_null, is_error );

}

void percentile_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )

{

if (args->args[0]!=NULL)

{

percentile_data *buffer = (percentile_data*)initid->ptr;

if (buffer->count>=BUFFERSIZE)

{

buffer->pages++;

buffer->count=0;

buffer->values=(double *) realloc(buffer->values,BUFFERSIZE*buffer->pages*sizeof(double));

}

if(args->arg_type[0]==INT_RESULT){

buffer->values[buffer->abscount++] = (double) *((longlong*)args->args[0]);

}

else{

buffer->values[buffer->abscount++] = *((double*)args->args[0]);

}

buffer->count++;

}

}

int compare_doubles (const void *a, const void *b)

{

const double *da = (const double *) a;

const double *db = (const double *) b;

return (*da > *db) - (*da < *db);

}

double percentile( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )

{

percentile_data* buffer = (percentile_data*)initid->ptr;

double pctile;

if (buffer->abscount==0 || *is_error!=0)

{

*is_null = 1;

return 0.0;

}

*is_null=0;

if (buffer->abscount==1)

{

return buffer->values[0];

}

qsort(buffer->values,buffer->abscount,sizeof(double),compare_doubles);

if(args->arg_type[1]==INT_RESULT){

pctile = (double) *((longlong*)args->args[1]);

}

else if(args->arg_type[1]==DECIMAL_RESULT){

pctile = atof(args->args[1]);

}

else{

pctile = *((double*)args->args[1]);

}

int n = buffer->abscount - 1;

if(pctile <=0){

return buffer->values[0];

}

if(pctile>=1){

return buffer->values[n];

}

double i = n * pctile;

int ix = (int) i;

if (i == ix)

{

return buffer->values[ix];

} else

{

int j = ix + 1 >= n ? n : ix + 1;

return(buffer->values[ix]*(j - i) + buffer->values[j]*(i - ix));

}

}

#endif

将以上源代码编译成.so文件

gcc -fPIC -Wall -I /usr/include/mysql/ -shared -o udf_percentile.so udf_percentile.cc

在ubuntu下,如果没有/usr/include/mysql, 需要先安装libmysqlclient-dev:sudo apt-get install libmysqlclient-dev。如果是mysql5.x,你可以下载我编译好的so文件。

将so文件拷贝到mysql的插件目录下:

sudo cp udf_percentile.so /usr/lib/mysql/plugin/

以管理员身份进入mysql,注册自定义函数:

CREATE AGGREGATE FUNCTION percentile RETURNS REAL SONAME 'udf_percentile.so';

使用方法:

SELECT percentile(score, 0.9991,5) FROM candidates;

0.9991就是百分位(99.91%),5是指结果的精度(小数位数)。

没有mysql服务的管理权限的,只能通过程序实现了,最后附上percentile的JAVA和JS实现。

JAVA:

public static double percentile(double[] data,double p){

int n = data.length;

Arrays.sort(data);

double px = p*(n-1);

int i = (int)java.lang.Math.floor(px);

double g = px - i;

if(g==0){

return data[i];

}else{

return (1-g)*data[i]+g*data[i+1];

}

}

JS:

const percentile = (data, p) =>{

let n = data.length;

data.sort((a, b) => a - b);

let px = p*(n-1);

let i = Math.floor(px);

let g = px - i;

if(g==0){

return data[i];

}else{

return (1-g)*data[i]+g*data[i+1];

}

}

mysql求分位数_给Mysql加自定义函数计算百分位数(percentile)。相关推荐

  1. mysql求分位数_分位函数(四分位数)概念与pandas中的quantile函数

    函数原型 DataFrame.quantile(q=0.5, axis=0, numeric_only=True, interpolation='linear') 参数 - q : float or ...

  2. MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结

    MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结 一.VARCHAR存储和行长度限制 1.VARCHAR(N)中,N指的是字符的长度,VARCHAR类型最大支持65535,指的是 ...

  3. pandas编写自定义函数计算多个数据列的加和(sum)、使用groupby函数和apply函数聚合计算分组内多个数据列的加和

    pandas编写自定义函数计算多个数据列的加和(sum).使用groupby函数和apply函数聚合计算分组内多个数据列的加和 目录

  4. R语言编写自定义函数计算R方、使用自助法Bootstrapping估计多元回归模型的R方的置信区间、可视化获得的boot对象、估计单个统计量的置信区间、分别使用分位数法和BCa法

    R语言编写自定义函数计算R方.使用自助法Bootstrapping估计多元回归模型的R方的置信区间.可视化获得的boot对象.估计单个统计量的置信区间.分别使用分位数法和BCa法(Bootstrapp ...

  5. Python Turtle 绘图[难度2星]:一朵雪花(基础代码 、 加变量/加自定义函数优化)

    2022年北京冬奥会开幕式上"一朵雪花"贯穿始终,给大家印象深刻.今天我们也让海龟来绘制一朵雪花.先绘制一朵普通雪花,在下一期分享中再让海龟来绘制一朵"中国结雪花&quo ...

  6. python函数求n年后本息_Python自定义函数计算给定日期是该年第几天的方法示例...

    本文实例讲述了Python自定义函数计算给定日期是该年第几天的方法.分享给大家供大家参考,具体如下: 写一个函数,计算给定日期是该年的第几天. 满足闰年的条件: 闰年是公历中的名词,能被4整除但不能被 ...

  7. Python使用numpy包编写自定义函数计算平均绝对误差(MAE、Mean Absolute Error)、评估回归模型和时间序列模型、解读MAE

    Python使用numpy包编写自定义函数计算平均绝对误差(MAE.Mean Absolute Error).评估回归模型和时间序列模型.解读MAE 目录

  8. python编写自定义函数计算一维numpy数组中与指定目标数值最接近(距离最近)的数值(find closest value in numpy array to a certain value)

    python编写自定义函数计算一维numpy数组中与指定目标数值最接近(距离最近)的数值(find closest value in numpy array to a certain value) 目 ...

  9. Python使用numpy包编写自定义函数计算均方误差(MSE、mean squared error)、评估回归模型和时间序列模型、解读MSE评估指标

    Python使用numpy包编写自定义函数计算均方误差(MSE.mean squared error).评估回归模型和时间序列模型.解读MSE评估指标 目录

最新文章

  1. 'or'='or'经典漏洞原理分析
  2. 友盟分享和cocos2dx符合重复duplicate symbol 解决方案
  3. python mysqldb cursor_python中MySQLdb模块用法实例
  4. linux go redis,go-redis 连接池
  5. QT4 自定义槽和信号
  6. 看阿里云如何用云上技术创新,帮助哈啰单车实现智能数据收治
  7. java如何实例化集合_如何在java中实例化一个Queue对象?
  8. 弗吉尼亚州为数据中心建设的电力线路产生争议
  9. TensorFlow神经网络(九)VGG net论文阅读笔记
  10. 运用提示原则证明线性无关
  11. Python网页爬虫之中文乱码
  12. 【 javascript 】.innerHTML属性定义
  13. 【回归预测】基于matlab灰狼算法优化ELMAN神经网络回归预测【含Matlab源码 1782期】
  14. 侠客X部分截图 官方论坛开发注册 邀您一起公测。
  15. Servlet各种接口和类
  16. 最新超完整的易支付PHP源码+代码全开源
  17. Pytorch优化器全总结(二)Adadelta、RMSprop、Adam、Adamax、AdamW、NAdam、SparseAdam(重置版)
  18. 简单的外网映射工具natapp操作
  19. grep exclude
  20. 简普科技Q3财报解读:业绩超过预期之后的更多确定性

热门文章

  1. Echarts曲线渐变色lineStyle
  2. 程序员非常实用的十个工具网站,值得收藏
  3. 右击文件夹转圈圈,有时卡死
  4. sasl java_java SASL_SSL 帐号密码 方式访问 kafka
  5. wampServer:橙色变绿色
  6. ansible管理界面_Ansible和Google日历集成,用于变更管理
  7. sumo交通流仿真软件的使用说明
  8. 疑问点sqlilibs 第一关
  9. 安防摄像头RTSP/Onvif协议网页无插件直播视频流媒体服务器EasyNVR之按需直播如何有效利用最大上行带宽
  10. 26岁零基础想转行做软件测试可行吗?多方面分析