我有一个包含日期,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
所以基本上我想要SELECT DISTINCT(日期),然后为每个日期执行上面的SELECT,其前面是INSERT INTO table2(...)将结果写入table2。
感谢您的帮助, 休
答案 0 :(得分:0)
我最终通过使用临时表开发了一个可接受的解决方案。也许不是最佳解决方案,但它在百万+记录表上的工作时间约为5秒。
我的临时表(t1)包含日期和日期行数。
上面的第三个选择更改为 SELECT t1.date,t1.cnt,id,value FROM t1 LEFT JOIN temp ON(t1.date = temp.date)
此外,上面第一个SELECT中的计算更改为使用c.cnt而不是@rank,并创建了@prevDate变量以重置日期更改的排名计数。
感谢任何看过这个并试图找到解决方案的人。
答案 1 :(得分:0)
我试图解决这个问题很长一段时间,然后我找到了以下答案。老实说。即使对于大桌子也很快(我使用它的桌子包含大约5密耳的记录,需要几秒钟)。
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;
您可以想象只需将table_name和field_name替换为您的表格和列名称。
有关详细信息,请查看Roland Bouman的原始帖子