我有一个存储过程,它根据某个组返回集合的中位数。
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%的任何项目选择。
答案 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) )