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

Postgresウィンドウ関数とgroupby例外

    あなたはそうではありません 実際、集計関数を使用しています。 ウィンドウ関数を使用しています 。そのため、PostgreSQLはsp.payoutを要求します およびs.buyin GROUP BYに含まれる 条項。

    OVERを追加する 句、集計関数sum() はウィンドウ関数に変換され、保持しながらパーティションごとに値を集計します。 すべての行。

    ウィンドウ関数と集計関数を組み合わせることができます 。集計が最初に適用されます。あなたの説明から、イベントごとに複数のペイアウト/バイインをどのように処理したいかがわかりませんでした。推測として、私はイベントごとにそれらの合計を計算します。 sp.payoutを削除できます およびs.buyin GROUP BYから 句を使用して、playerごとに1行を取得します およびevent

    SELECT p.name
         , e.event_id
         , e.date
         , sum(sum(sp.payout)) OVER w
         - sum(sum(s.buyin  )) OVER w AS "Profit/Loss" 
    FROM   player            p
    JOIN   result            r ON r.player_id     = p.player_id  
    JOIN   game              g ON g.game_id       = r.game_id 
    JOIN   event             e ON e.event_id      = g.event_id 
    JOIN   structure         s ON s.structure_id  = g.structure_id 
    JOIN   structure_payout sp ON sp.structure_id = g.structure_id
                              AND sp.position     = r.position
    WHERE  p.player_id = 17 
    GROUP  BY e.event_id
    WINDOW w AS (ORDER BY e.date, e.event_id)
    ORDER  BY e.date, e.event_id;
    

    この式の場合:sum(sum(sp.payout)) OVER w 、外側のsum() はウィンドウ関数であり、内部のsum() は集計関数です。

    p.player_idを想定 およびe.event_id PRIMARY KEYです それぞれのテーブルで。

    e.event_idを追加しました ORDER BYWINDOWの 決定論的なソート順に到達するための句。 (同じ日に複数のイベントが発生する可能性があります。)event_idも含まれています 結果として、1日あたりの複数のイベントを区別します。

    クエリはシングルに制限されますが プレーヤー(WHERE p.player_id = 17 )、p.nameを追加する必要はありません またはp.player_id GROUP BYへ およびORDER BY 。結合の1つが行を不当に乗算する場合、結果の合計は正しくありません(部分的または完全に乗算されます)。 p.nameによるグループ化 その場合、クエリを修復できませんでした。

    e.dateも削除しました GROUP BYから 句。主キーe.event_id PostgreSQL9.1以降の入力行のすべての列をカバーしています。

    もし 一度に複数のプレーヤーを返すようにクエリを変更し、適応させます:

    ...
    WHERE  p.player_id < 17  -- example - multiple players
    GROUP  BY p.name, p.player_id, e.date, e.event_id  -- e.date and p.name redundant
    WINDOW w AS (ORDER BY p.name, p.player_id, e.date, e.event_id)
    ORDER  BY p.name, p.player_id, e.date, e.event_id;
    

    p.nameでない限り player_idによって一意(?)、グループ、順序で定義されます さらに、決定論的なソート順で正しい結果を取得します。

    e.dateのみを保持しました およびp.name GROUP BYで パフォーマンス上の利点を期待して、すべての句で同じソート順を持つようにします。それ以外の場合は、そこで列を削除できます。 (e.dateについても同様です 最初のクエリで。)




    1. WebページのHTMLテーブル内にMySQLデータベーステーブルの値を表示する

    2. SQLのデータ型のサイズを変更します

    3. Postgres:タイムスタンプを最も近い分に切り上げるまたは切り下げるにはどうすればよいですか?

    4. パート2–大規模なデータベース図を整理する方法