mysql按组的百分位排名

mysql按组的百分位排名,mysql,statistics,Mysql,Statistics,我有一个包含日期、id和值的表,每个日期大约有1000个id行。我需要按日期计算每行的百分位排名。我使用以下代码对单个日期进行百分位排名,但对于超过10年的每日数据,按日期运行是非常低效的。似乎它应该能够在MySQL中进行公式化,但我一直无法使它工作 Date ID Value date1 01 -7.2 date1 02 0.6 date2 01 1.2 date2 02 3.8 SELECT c.id, c.value, ROUND( ( (

我有一个包含日期、id和值的表,每个日期大约有1000个id行。我需要按日期计算每行的百分位排名。我使用以下代码对单个日期进行百分位排名,但对于超过10年的每日数据,按日期运行是非常低效的。似乎它应该能够在MySQL中进行公式化,但我一直无法使它工作

Date   ID    Value
date1  01    -7.2
date1  02     0.6
date2  01     1.2
date2  02     3.8

SELECT c.id, c.value, ROUND( (
(@rank - rank) / @rank ) *100, 2) AS rank
FROM (
SELECT * , @prev := @curr , @curr := a.value, 
@nxtRnk := @nxtRnk + 1,
@rank := IF( @prev = @curr , @rank , @nxtRnk ) AS rank
FROM (
SELECT id, value
FROM temp
WHERE date = '2013-06-28'
) AS a, (

SELECT @curr := NULL , @prev := NULL , @rank :=0, @nxtRnk :=0
) AS b
ORDER BY value DESC
) AS c
所以基本上我想选择DISTINCT(date),然后对每个日期执行上面的选择,这是在INSERT INTO table2(…)之前将结果写入table2

谢谢你的帮助,
Hugh

我最终通过使用临时表开发出了一个可接受的解决方案。也许不是最佳的解决方案,但在一张百万以上的记录表上,它只需5秒左右

我的临时表(t1)包含日期和日期行数

上面的第三个选择更改为 选择t1.date,t1.cnt,id,从t1左连接临时打开的值(t1.date=temp.date)

此外,上面第一个选择中的计算更改为使用c.cnt而不是@rank,并且创建了@prevDate变量以重置日期更改时的排名计数


感谢所有看过这篇文章并试图找到解决方案的人。

我花了很长时间试图解决这个问题,然后我找到了以下答案。真是太棒了。即使对于大的表,速度也相当快(我使用它的表包含大约5 mil记录,需要几秒钟)

可以想象,只要用表名和列名替换表名和字段名即可

有关更多信息,请查看的原始帖子

SELECT 
    CAST(SUBSTRING_INDEX(SUBSTRING_INDEX( GROUP_CONCAT(field_name ORDER BY 
    field_name SEPARATOR ','), ',', 95/100 * COUNT(*) + 1), ',', -1) AS DECIMAL) 
    AS 95th Per 
FROM table_name;