Postgresql

使用 array_position() 函式從 pg_stats 獲取列的最頻繁值

  • July 14, 2018

我正在嘗試執行這個簡單的查詢,以檢查某個值(1000)是否屬於 Postgres 查詢優化器使用的 MCV 列表:

SELECT array_position(most_common_vals, 1000) 
FROM pg_stats 
WHERE tablename = 'tenk1' 
AND attname = 'unique1';

但收到以下錯誤消息:

ERROR:  function array_position(anyarray, integer) does not exist

如何修復?

array_position()是此處描述的標準函式,以下語句按預期返回2 :

SELECT array_position('{1,2,3}', 2);

解決方案

假設您的列的數據類型tenk1.unique1integer

SELECT array_position(most_common_vals::text::int[], 1000) 
FROM   pg_stats 
WHERE  tablename = 'tenk1' 
AND    attname = 'unique1';

使用您的實際列類型和相應的數組類型。

您將獲得該位置,如果該值不在 MCV 列表中,則為 NULL。

解決方案很短 - 不像…

解釋

該函式array_position()被定義為採取(anyarray, anyelement)(或(anyarray, anyelement, integer)用於第二個變體)。

該列pg_stats.most_common_vals具有多態數據類型**anyarray**,能夠保存任何數據類型的數組 - 原因很明顯。

anyarray並且anyelement不允許作為使用者創建的表的數據類型。對於使用者來說,兩者都是多態偽類型。(但 Postgres 可以在系統表中使用它們。)

同一函式中的多個多態變數必須解析為相同(或相應)的數據類型。手冊:

此外,如果聲明了位置anyarray和聲明了其他位置,則位置anyelement中的實際數組類型anyarray必須是其元素與出現在任何元素位置中的相同類型的數組。

和:

因此,當使用多態類型聲明多個參數位置時,最終效果是只允許實際參數類型的某些組合

大膽強調我的。

您發現了一個極端情況,即多態與第二個位置的- 或任何非多態類型的組合導致函式類型解析失敗。anyarray``integer

1000在您的表達式array_position(most_common_vals, 1000)中是一個解析為integer. 這些將以類似的方式失敗:

array_position(most_common_vals, '1000')  -- untyped string literal
ERROR:  function array_position(anyarray, unknown) does not exist
array_position(most_common_vals, '1000'::text)
ERROR:  function array_position(anyarray, text) does not exist

此外,沒有為 定義強制轉換anyarray,它是使用者域中的偽類型:

SELECT * FROM pg_cast WHERE castsource = 'anyarray'::regtype;  -- nothing found

解決方法是將 totext作為踏腳石,因為任何類型都可以轉換為text. 然後轉換為integer[],得到上面的解決方案。

最後,我認為這是函式類型解析的一個缺點,可以解決(容易嗎?)。但是由於數據類型anyarray不應該像這樣在使用者領域開始使用,我懷疑任何開發人員都會花時間在它上面……

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