重写存储过程以返回而不是中位数(50%),项目在20%/ 30%等位置

时间:2011-05-02 10:08:01

标签: mysql sql stored-procedures

我有一个存储过程,它根据某个组返回集合的中位数。

SET @myvar:='1';
SET @rownum=0;

SELECT result.readdate, 
       AVG(total_gallons) AS total_gallons
FROM   (SELECT middle_rows.readdate, 
               numerated_rows.rownum, 
               numerated_rows.total_gallons 
        FROM   (SELECT IF(@myvar = readdate, @rownum := IFNULL(@rownum,0) + 1, @rownum := 0) AS rownum,
                       @myvar := readdate                                          AS readdate_alias,
                       total_gallons 
                FROM   _temp_total_gallons 
                ORDER  BY readdate, 
                          total_gallons) numerated_rows, 
               (SELECT readdate, 
                       COUNT(*) / 2 median 
                FROM   _temp_total_gallons
                GROUP  BY readdate) middle_rows 
        WHERE  numerated_rows.rownum BETWEEN ( middle_rows.median - IF(median = ROUND(median), 1, 0) - 0.5 ) AND ( middle_rows.median - IF(median = ROUND(median), 0, 0.5) )
               AND numerated_rows.readdate_alias = middle_rows.readdate) result
GROUP  BY readdate;

如您所见,这使用BETWEEN子句在50%位置之间返回行。如果找到多行(甚至设置),则外部选择会产生平均值。

我尝试将COUNT(*) / 2 median更改为COUNT(*) / 5 median,但查询返回的数据集要小得多,可能是因为between子句太严格而且没有反映20%。

在如下的集合中:

1 (2) 3 4 5 6 7 8 9 100 110

数字2为20%。

将来我希望脚本可用于返回30%或40%的任何项目选择。

2 个答案:

答案 0 :(得分:1)

看看下一页的信息,SQL能够计算出你想要的任何百分位数

http://rpbouman.blogspot.com/2008/07/calculating-nth-percentile-in-mysql.html

我自己在很多领域都使用过它,而且效果非常好。你只需要小心'group_concat_max_len'参数的值,因为这个参数太小会搞砸你的结果。

希望它有所帮助!

戴夫

答案 1 :(得分:0)

问题出在BETWEEN子句中,正如您所推断的那样。 请尝试以下BETWEEN子句:

WHERE  numerated_rows.rownum  BETWEEN ( middle_rows.median - 1.0001 ) AND ( middle_rows.median - 0.0001) )