2014-12-03 77 views
2

有下列設置了在Postgres 9.3:不必要的postgres數組轉換?

CREATE TABLE t (id INTEGER); 
INSERT INTO t VALUES (1), (2), (3); 

我彙總這些值到數組(不要問爲什麼,實際的設置是非常複雜的,所以我只需要這個方法)。

現在我需要檢查一些整數是否屬於數組。試過這樣:

SELECT 1=ANY((SELECT array_agg(id) FROM t)) 

遇到錯誤:

ERROR: operator does not exist: integer = integer[] 
LINE 1: SELECT 1=ANY((SELECT array_agg(id) FROM t)) 
       ^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 

一些試驗後,發現了一個有效的解決方案:

SELECT 1=ANY((SELECT array_agg(id) FROM t)::integer[]) 

爲什麼Postgres的要求我投整數[]整數[]?沒有意義。

回答

2

內部選擇的結果(SELECT array_agg(id) FROM t)不是integer[]它是包含單個行的結果集,其中包含integer[]

您可以通過兩種方式公開發生了什麼事情。

如果您嘗試

SELECT 1=ANY((SELECT array_agg(id) FROM t)::text[]);

錯誤消息是 ERROR: operator does not exist: integer = text

注意,錯誤消息並不指text[]但到text

這是因爲相等是比較右參數的每個元素的左參數。因此,在您原來的查詢中,它是integer[]的結果集,它試圖將1與每個(您只有一個)integer[]進行比較。

另一種方式看,這是反思

select count(*) from (select array_agg(id) from t) as z

這將嵌入原來的子查詢爲z - 它返回1行。如果您嘗試將z轉換爲integer[],它將無法工作 - 因爲FROM子句需要結果集而不是整數數組。

但是,可以將包含具有一列的一行的結果集轉換爲該單例類型的實例(在本例中爲integer[])。這消除了「我正在查看這個子查詢的任何行」到「我正在查看這個子查詢的單行/列的數組」。

因此,明確施放的要求。