postgres select TOP X in group 查詢每一個組的前幾名

參考: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名過濾出來。 

相關文章
相關標籤/搜索