这是我当前的查询,它有效,但速度很慢:
SELECT row, MIN(flg) ||' to ' ||Max (flg) as xyz , avg(amt_won), count(*)
FROM(
SELECT (ROW_NUMBER() OVER (ORDER BY flg))*100/
(SELECT count(*)+100 as temprow FROM temporary_six_max) as row, flg, amt_won
FROM temporary_six_max
JOIN (
SELECT id_player AS pid, avg(flg_vpip::int) AS flg
FROM temporary_six_max
GROUP BY id_player
) AS auxtable
ON pid = id_player
) as auxtable2
group by 1
order by 1;
我在固定(或几乎固定)的100个范围内进行分组,这些范围由按id_player分组的avg(flg_vpip)排序。
在这里,我粘贴了结果,以防有助于理解: https://spreadsheets0.google.com/ccc?key=tFVsxkWVn4fMWYBxxGYokwQ&authkey=CNDvuOcG&authkey=CNDvuOcG#gid=0
我想知道在这种情况下是否有比ROW_NUMBER()更好的功能,我觉得我做了太多的子选择,但我不知道如何优化它。
我非常感谢任何帮助。
如果不清楚,请告诉我。
谢谢。
编辑:
我创建auxtable 2的原因是因为当我使用(ROW_NUMBER()OVER(ORDER BY flg),并使用其他agregate命令,如avg(amt_won)和count(*),这是必不可少的,我得到一个错误说flg应该在聚合函数中,但是我不能用flg的聚合函数来命令。
答案 0 :(得分:2)
我生成了一些数据来测试,如下所示:
create table temporary_six_max as
select id_player, flg_vpip,
random()*100 * (case flg_vpip when 0 then 1 else -1 end) as amt_won
from (select (random()*1000)::int as id_player, random()::int as flg_vpip
from generate_series(1,1000000)) source;
create index on temporary_six_max(id_player);
你的查询成功运行,但是并没有完全生成相同的计划,我在下臂得到一个嵌套循环而不是init-plan中的合并和seq扫描 - 你还没有关闭enable_seqscan我希望吗?
只使用表格的单次扫描的解决方案:
select row, min(flg) || ' to ' || max(flg) as xyz, avg(amt_won), count(*)
from (select flg, amt_won, ntile(100) over(order by flg) as row
from (select id_player as pid, amt_won,
avg(flg_vpip::int) over (partition by id_player) as flg
from temporary_six_max
) player_stats
) chunks
group by 1
order by 1
坏消息是,这实际上会在我的机器上执行更糟,特别是如果我将work_mem提升到足以避免第一次磁盘排序(制作player_stats,按flg排序)。虽然增加work_mem确实将查询时间减半,但我想这至少是一个开始?
话虽如此,我的查询运行了大约5秒钟来处理temporary_six_max中的10E6输入行,这比你发布的要快一个数量级。您的表是否适合您的缓冲区缓存?如果没有,单扫描解决方案对您来说可能更好。 (您使用的是哪个版本的Postgresql?“解释(分析,缓冲)选择...”将显示9.0中的缓冲区命中/未命中率,或者只查看“shared_buffers”设置并与表格大小进行比较)