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

mysqlの一連の行の累積合計

    更新

    MySQL 8.0では、SQL Serverの「ウィンドウ関数」と同等の機能である「ウィンドウ関数」が導入されています(Transact-SQL OVERによって提供されるパーティション分割と順序付けを使用) 構文)、およびOracleの「分析関数」。

    MySQLリファレンスマニュアル12.21ウィンドウ関数 https://dev.mysql .com / doc / refman / 8.0 / en / window-functions.html

    ここで提供される答えは、8.0より前のバージョンのMySQLに対するアプローチです。

    元の回答

    MySQLは、他のDBMS(OracleやSQL Serverなど)で使用可能な分析関数のように、実行中の「累積合計」を取得するために使用する型分析関数を提供していません。

    ただし、MySQLを使用して、一部の分析関数をエミュレートすることは可能です。

    (少なくとも)2つの実行可能なアプローチがあります:

    1つは、相関サブクエリを使用して小計を取得することです。このアプローチは、大規模なセットではコストがかかる可能性があり、外部クエリの述語が複雑な場合は複雑になる可能性があります。 「複数のテーブルでの複数の結合」がどれほど複雑かによって異なります。 (残念ながら、MySQLもCTEをサポートしていません。)

    もう1つのアプローチは、MySQLユーザー変数を使用して、コントロールブレーク処理を実行することです。ここでの「トリック」は、(ORDER BYを使用して)ソートされたクエリの結果を取得し、クエリを別のクエリでラップすることです。

    後者のアプローチの例を示します。

    MySQLが操作を実行する順序のため、cumulative_total idの値の前に列を計算する必要があります およびday 現在の行からユーザー変数に保存されます。この列を最初に配置するのが最も簡単です。

    (以下のクエリで)iとしてエイリアスされたインラインビューは、ユーザー変数がセッションですでに設定されている場合に備えて、ユーザー変数を初期化するためにあります。それらにすでに値が割り当てられている場合は、現在の値を無視する必要があります。これを行う最も簡単な方法は、それらを初期化することです。

    元のクエリは括弧で囲まれ、エイリアスcが与えられます 以下の例では。元のクエリに対する唯一の変更は、ORDER BY句の追加であるため、クエリの行を順番に処理することができます。

    外側の選択は、idかどうかをチェックします およびday 現在の行の値は前の行と「一致」します。含まれている場合は、amountを追加します 現在の行から累積小計まで。それらが一致しない場合は、累積小計をゼロにリセットし、現在の行からの金額を追加します(または、より簡単に言えば、現在の行からの金額を割り当てるだけです)。

    累積合計の計算が完了したら、idを保存します。 およびday 現在の行の値をユーザー変数に変換するため、次の行を処理するときに使用できます。

    例:

    SELECT IF(@prev_id = c.id AND @prev_day = c.day
             ,@cumtotal := @cumtotal + c.amount
             ,@cumtotal := c.amount) AS cumulative_total
         , @prev_id  := c.id  AS `id`
         , @prev_day := c.day AS `day`
         , c.hr
         , c.amount AS `amount'
      FROM ( SELECT @prev_id  := NULL
                  , @prev_day := NULL
                  , @subtotal := 0
           ) i
      JOIN (
    
             select id, day, hr, amount from
             ( //multiple joins on multiple tables)a
             left join
             (//unions on multiple tables)b
             on a.id=b.id
    
             ORDER BY 1,2,3
           ) c
    

    累積合計を最後の列として、別の順序で列を返す必要がある場合、1つのオプションは、ステートメント全体を一連の親でラップし、そのクエリをインラインビューとして使用することです。

    SELECT d.id
         , d.day
         , d.hr
         , d.amount
         , d.cumulative_total
    FROM (
           // query from above
         ) d
    


    1. 照合の不正な組み合わせMySQLエラー

    2. クエリ内でDML操作を実行できない解決策はありますか?

    3. MySQLで部分文字列を抽出する方法

    4. SQLServerでのカスタムの日付/時刻の書式設定