sql >> データベース >  >> RDS >> PostgreSQL

循環平均用のカスタムPostgreSQL集計

    ARRAYを利用できます 内部で入力します。引数の型は、引き続き任意の数値型にすることができます。 floatを使用したデモンストレーション (=double precision ):

    CREATE OR REPLACE FUNCTION f_circavg (float[], float)
      RETURNS float[] LANGUAGE sql STRICT AS
    'SELECT ARRAY[$1[1] + sin($2), $1[2] + cos($2), 1]';
    
    CREATE OR REPLACE FUNCTION f_circavg_final (float[])
      RETURNS float  LANGUAGE sql AS
    'SELECT CASE WHEN $1[3] > 0 THEN atan2($1[1], $1[2]) END';
    
    CREATE AGGREGATE circavg (float) (
       sfunc     = f_circavg
     , stype     = float[]
     , finalfunc = f_circavg_final
     , initcond  = '{0,0,0}'
    );

    遷移関数f_circavg() STRICTが定義されています 、したがって、NULLの行は無視されます 入力。また、3番目の配列要素を設定して、1つ以上の入力行を持つセットを識別します。それ以外の場合はCASE 最後の関数はNULLを返します 。

    テスト用の一時テーブル:

    CREATE TEMP TABLE t (x float);
    INSERT INTO t VALUES (2), (NULL), (3), (4), (5);
    

    NULLを投入しました STRICTもテストする値 マジック。電話:

    SELECT circavg(x) FROM t;
    
           circavg
    -------------------
     -2.78318530717959
    

    クロスチェック:

    SELECT atan2(sum(sin(x)), sum(cos(x))) FROM t;
    
           atan2
    -------------------
     -2.78318530717959
    

    同じを返します。動作しているようです。より大きなテーブルを使用したテストでは、通常の集計関数を使用した最後の式は、カスタム集計よりも4倍高速でした。

    入力行がゼロ/NULL入力のみをテストします:

    SELECT circavg(x) FROM t WHERE false;     -- no input rows
    SELECT circavg(x) FROM t WHERE x IS NULL; -- only NULL input
    

    NULLを返します どちらの場合も。



    1. MySQLでの参照と結合の永続性とは何ですか?

    2. Postgresqlは複数行でgroupbyします

    3. JPAフラッシュとコミット

    4. レコードを削除しないステートメントの削除