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

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

    繰り返しになりますが、いくつかの「データ型」以上のものについては、crosstab()を使用することをお勧めします :

    SELECT * FROM crosstab(
         $$SELECT DISTINCT ON (1, 2)
                  'max' AS "type", data_type, val
           FROM   tbl
           ORDER  BY 1, 2, val DESC$$
    
        ,$$VALUES ('Final Fantasy'), ('Quake 3'), ('World of Warcraft')$$)
    AS x ("type" text, "Final Fantasy" int, "Quake 3" int, "World of Warcraft" int)
    

    返品:

    type | Final Fantasy | Quake 3 | World of Warcraft
    -----+---------------+---------+-------------------
    max  | 500           | 1500    |    1200
    

    基本の詳細説明:
    PostgreSQLクロス集計クエリ

    動的ソリューション

    トリッキーなことは、これを完全に動的にすることです。 :それを機能させるために

    • 不明な番号 列の数(この場合はdata_types)
    • 不明な名前 (再びdata_types)

    少なくともタイプ よく知られています:integer この場合。

    つまり、現在のPostgreSQL(9.3を含む)では不可能です。多態的なタイプの近似と、配列またはhstoreタイプの制限を回避する方法があります。あなたにとって十分かもしれません。しかし、それは厳密には不可能です 単一のSQLクエリの個々の列で結果を取得します。 SQLは型について非常に厳格であり、何を期待できるかを知りたがっています。

    ただし two で実行できます クエリ。最初のものは、使用する実際のクエリを作成します。上記の単純なケースに基づいて構築:

    SELECT $f$SELECT * FROM crosstab(
         $$SELECT DISTINCT ON (1, 2)
                  'max' AS "type", data_type, val
           FROM   tbl
           ORDER  BY 1, 2, val DESC$$
    
        ,$$VALUES ($f$     || string_agg(quote_literal(data_type), '), (') || $f$)$$)
    AS x ("type" text, $f$ || string_agg(quote_ident(data_type), ' int, ') || ' int)'
    FROM  (SELECT DISTINCT data_type FROM tbl) x
    

    これにより、実際に必要なクエリが生成されます。 同じトランザクション内で2番目のトランザクションを実行します 同時実行の問題を回避するため。

    quote_literal()の戦略的な使用に注意してください およびquote_ident() あらゆる種類の不正な(列の)名前をサニタイズし、SQLインジェクションを防止します。 。

    ドル相場の複数の層に混乱しないでください。これは、動的クエリを構築するために必要です。できるだけシンプルにしています。



    1. 'ANY'を含むPostgreSQLクエリが機能していません

    2. MySQLで行をフィルタリングする句

    3. OracleでPLSQLブロックを実行する方法

    4. ステートメントのINSERTINTO...部分を繰り返さずに、複数の行を挿入しますか?