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

動的クロス集計クエリを実行する

    あなたが求めているのは不可能です 。 SQLは厳密に型指定された言語です。 PostgreSQL関数はリターンタイプを宣言する必要があります(RETURNS ..作成の時点

    これを回避する限られた方法は、多形関数を使用することです。関数呼び出し時間にリターンタイプを指定できる場合 。しかし、それはあなたの質問からは明らかではありません。

    • PL / pgSQL関数をリファクタリングして、さまざまなSELECTクエリの出力を返します

    できます 匿名レコードで完全に動的な結果を返します。ただし、すべての呼び出しで列定義リストを提供する必要があります。そして、返された列についてどのように知っていますか?キャッチ22。

    必要なものや使用できるものに応じて、さまざまな回避策があります。すべてのデータ列が同じデータ型を共有しているように見えるため、配列を返すことをお勧めします text[] 。または、hstoreのようなドキュメントタイプを返すこともできます またはjson 。関連:

    • CASEおよびGROUPBYを使用したピボットの動的な代替手段

    • hstoreキーを未知のキーセットの列に動的に変換します

    ただし、2つの呼び出しを使用する方が簡単な場合があります。1:Postgresにクエリを作成させます。 2:返された行を実行して取得します。

    • 単一のSQLステートメントを使用して複数のmax()値を選択する

    私はあなたの質問で提示されたEricMinikelの関数を使用しません 。悪意を持って不正な形式の識別子によるSQLインジェクションに対しては安全ではありません。 format()を使用する Postgres 9.1より古いバージョンを実行していない限り、クエリ文字列を作成します。

    短くてクリーンな実装は次のようになります:

    CREATE OR REPLACE FUNCTION xtab(_tbl regclass, _row text, _cat text
                                  , _expr text  -- still vulnerable to SQL injection!
                                  , _type regtype)
      RETURNS text AS
    $func$
    DECLARE
       _cat_list text;
       _col_list text;
    BEGIN
    
    -- generate categories for xtab param and col definition list    
    EXECUTE format(
     $$SELECT string_agg(quote_literal(x.cat), '), (')
            , string_agg(quote_ident  (x.cat), %L)
       FROM  (SELECT DISTINCT %I AS cat FROM %s ORDER BY 1) x$$
     , ' ' || _type || ', ', _cat, _tbl)
    INTO  _cat_list, _col_list;
    
    -- generate query string
    RETURN format(
    'SELECT * FROM crosstab(
       $q$SELECT %I, %I, %s
          FROM   %I
          GROUP  BY 1, 2  -- only works if the 3rd column is an aggregate expression
          ORDER  BY 1, 2$q$
     , $c$VALUES (%5$s)$c$
       ) ct(%1$I text, %6$s %7$s)'
    , _row, _cat, _expr  -- expr must be an aggregate expression!
    , _tbl, _cat_list, _col_list, _type
    );
    
    END
    $func$ LANGUAGE plpgsql;
    

    元のバージョンと同じ関数呼び出し。関数crosstab() 追加モジュールtablefuncによって提供されます インストールする必要があります。基本:

    • PostgreSQLクロス集計クエリ

    これにより、列名とテーブル名が安全に処理されます。オブジェクト識別子タイプregclassの使用に注意してください およびregtype 。スキーマ修飾名でも機能します。

    • PostgreSQL関数パラメータとしてのテーブル名

    ただし、完全に安全ではありません 式として実行する文字列を渡す間(_expr -cellc 元のクエリで)。この種の入力は、SQLインジェクションに対して本質的に安全ではないため、一般に公開しないでください。

    • Postgres関数でのSQLインジェクションと準備されたクエリ

    テーブルを1回だけスキャンします カテゴリの両方のリストで、少し速くなるはずです。

    それでも完全に動的な行タイプを返すことはできません。それは厳密には不可能だからです。



    1. 最も難しい質問のヘルプのための最高のSQLServerパフォーマンスフォーラム

    2. SQL Serverの挿入、更新、選択の最速の方法

    3. リモート接続MysqlUbuntu

    4. PostgreSQLクエリは制限1で非常に遅い