Postgresql

如何對聚合函式呼叫進行排序

  • March 20, 2020

如果我有一個昂貴的函式呼叫,它需要一個 JSONB 並返回一個 INT,例如

CREATE FUNCTION my_expensive_function(data JSONB) RETURNS INTEGER AS

如何通過在一組 JSON 數據上呼叫聚合結果來排序聚合結果,例如:

SELECT ARRAY_AGG(my_expensive_function(data) ORDER BY ???)
   FROM JSONB_ARRAY_ELEMENTS(json_set) data;

如果我嘗試為結果分配名稱,則會收到錯誤消息:

SELECT ARRAY_AGG(my_expensive_function(data) id ORDER BY id)
   FROM JSONB_ARRAY_ELEMENTS(json_set) data;

ERROR:  42601: syntax error at or near "id"
LINE 1: SELECT ARRAY_AGG(my_expensive_function(data) id ORDER BY id)...
                                                ^
LOCATION:  scanner_yyerror, scan.l:1134

我發現我可以通過呼叫該函式兩次來做到這一點,但我討厭這樣:

SELECT ARRAY_AGG(my_expensive_function(data) ORDER BY my_expensive_function(data))
   FROM JSONB_ARRAY_ELEMENTS(json_set) data;

我還發現這似乎可行,但也有點麻煩:

WITH data_set AS (
   SELECT my_expensive_function(data) AS id
   FROM JSONB_ARRAY_ELEMENTS(json_set) data
) SELECT ARRAY_AGG(id ORDER BY id) FROM data_set;

更新:我應該指定-我可以在單個查詢中做任何魔術還是必須使用 WITH/子查詢?為什麼我不能在函式的結果中添加名稱?

使用子查詢:

SELECT array_agg(x ORDER BY x)
FROM (SELECT my_expensive_function(data) AS x
     FROM jsonb_array_elements(json_set) AS data
    ) AS q;

my_expensive_function(data)另一種選擇是在LATERAL交叉連接中呼叫:

SELECT
 ARRAY_AGG(id ORDER BY id)
FROM
 JSONB_ARRAY_ELEMENTS(json_set) AS data
 CROSS JOIN LATERAL (SELECT my_expensive_function(data)) AS x (id)
;

或者,您可以使用逗號表示交叉連接:

SELECT
 ARRAY_AGG(id ORDER BY id)
FROM
 JSONB_ARRAY_ELEMENTS(json_set) AS data,
 LATERAL (SELECT my_expensive_function(data)) AS x (id)
;

引用自:https://dba.stackexchange.com/questions/262316