参考:python
https://stackoverflow.com/questions/27415706/postgresql-select-top-three-in-each-groupsql
http://charlesnagy.info/it/postgresql/group-by-limit-per-group-in-postgresql函数
但实在看不懂这里面LATERAL的用法,并且语法和pg11彷佛也有了区别。post
这个里面的LATERAL用法却是看懂了,把LATERAL当成foreach来用:性能
https://www.oschina.net/translate/postgresqls-powerful-new-join-type-lateral?cmpspa
简单说,用LATERAL JOIN2个子查询:.net
1 GROUP BY 获得聚合后的分组postgresql
2 再用这个数量缩水的 用WHERE inner.grp = outer.grp 去过滤没缩水前的所有数据。排序获得查询结果code
最终外面再包1层selectblog
——但若是inner是个view 等于里面要扫描N次 N等于1的group数量。
个人分组有点多,几百个,实测结果:要5秒钟,实在不能忍,性能太差了
最后,仍是用https://stackoverflow.com/questions/27415706/postgresql-select-top-three-in-each-group
里面最直接的窗口函数法,1次FROM就搞定,400ms,就算凑合了
SELECT * FROM( SELECT * ,ROW_NUMBER() OVER (PARTITION BY grp ORDER BY value DESC) AS order_in_grp FROM table1 ) AS A WHERE order_in_grp < 2
子查询里用窗口函数获得每一个分组内的序号order_in_grp:按grp字段分组,组内按value降序的序号
外层只是用WHERE过滤出每一个组内前1名。
对我这种新手来讲,仍是这样简单、直接、标准语法的方式更适合我。怎么用LATERAL才能效率高,暂时无暇顾及了。
起码符合The Zen of Python的前几条
Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity.
不是看见分组就必定要GROUP BY, 窗口函数这样反而更灵活——不聚合,而是,在子查询里给出组内排名order_in_grp字段,而后在外面作1次WHERE把每一个分组的前N名过滤出来。