web-dev-qa-db-ja.com

array_position()関数を使用して、pg_statsから列の最も頻繁な値を取得します。

いくつかの値(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()は、説明されている標準関数 here であり、次のステートメントは期待どおり2を返します。

_SELECT array_position('{1,2,3}', 2);
_
4
zer0hedge

解決

列のデータ型を想定すると、_tenk1.unique1_はintegerになります。

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

実際の列タイプと対応する配列タイプを使用します。
位置を取得します。値がMCVリストにない場合はNULLを取得します。

解決策は短いです-とは異なり...

説明

関数 array_position() は_(anyarray, anyelement)_(または2番目のバリアントの場合は_(anyarray, anyelement, integer)_)を取るように定義されています。

_pg_stats.most_common_vals_ は多相データ型anyarrayを持ち、あらゆるデータ型の配列を保持できます-明らかな理由があります。

anyarrayおよびanyelementは、ユーザーが作成したテーブルのデータ型として許可されていません。ユーザーの場合、どちらも polymorphic pseudo-types です。 (しかし、Postgresはシステムテーブルでそれらを使用できます。)

同じ関数内の複数のポリモーフィック変数は、同じ(または対応する)データ型に解決される必要があります。マニュアル:

さらに、anyarrayと宣言された位置とanyelementと宣言された位置がある場合、anyarray位置の実際の配列型は、anyelementに現れる要素と同じ型の要素を持つ配列でなければなりません。ポジション。

そして:

したがって、複数の引数の位置がポリモーフィック型で宣言されている場合、最終的な効果は実際の引数の型の特定の組み合わせのみが許可されるです。

大胆な強調鉱山。

多態性anyarrayinteger-またはanyの組み合わせで function type resolution が失敗するコーナーケースを見つけました2番目の位置に非ポリモーフィック型。

式の_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
_

回避策は、textにキャストできるため、飛び石としてtextにキャストすることです。次に_integer[]_にキャストして、上記のソリューションに到達します。

最後に、私は考えるこれは、(簡単に?)解決できる関数型解決の欠点です。しかし、データ型anyarrayは、ユーザーランドで最初にこのように使用することを想定していないため、開発者がそれに時間を費やすことはないと思います...

3