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

ローリングサムの実行方法、各行には前の行の合計を含める必要があります

    MySQLユーザー変数を利用して、分析関数をエミュレートできます。 (半結合の使用や相関サブクエリの使用など、他のアプローチもいくつかあります。より適切であると思われる場合は、それらのソリューションも提供できます。)

    「現在の合計」分析関数をエミュレートするには、次のようなものを試してください。

    SELECT t.user_id
         , t.starttime
         , t.order_number
         , IF(t.order_number IS NOT NULL,
             @tot_dur := 0,
             @tot_dur := @tot_dur + t.visit_duration_seconds) AS tot_dur
      FROM visit t
      JOIN (SELECT @tot_dur := 0) d
     ORDER BY t.user_id, t.start_time
    

    ここでの「トリック」は、IF関数を使用してorder_numberかどうかをテストすることです。 無効です。 nullの場合は、期間の値を変数に追加します。それ以外の場合は、変数をゼロに設定します。

    インラインビュー(別名d)を使用します 、@tot_dur変数がゼロに初期化されるようにします。

    注:このようなMySQLユーザー変数の使用には注意してください。上記のSELECTステートメントでは、SELECTリスト内の変数の割り当ては、ORDER BYの後に行われるため、決定論的な動作を得ることができます。

    そのクエリは、user_idの「ブレーク」を処理しません。これを取得するには、前の行のuser_idの値が必要になります。それを別のユーザー変数に保存できます。操作の順序は決定論的であり、前の行のuser_idを上書きする前に、累積を行うように注意する必要があります。

    tot_durの後にuser_idが表示されるように(またはuser_id列の2番目のコピーを含めるように)列を並べ替える必要があります

    SELECT t.user_id
         , t.starttime
         , t.order_number
         , IF(t.order_number IS NULL,
             @tot_dur := IF(@prev_user_id = t.user_id,@tot_dur,0) + t.visit_duration_seconds,
             @tot_dur := 0
           ) AS tot_dur
         , @prev_user_id := t.user_id AS prev_user_id
      FROM visit t
      JOIN (SELECT @tot_dur := 0, @prev_user_id := NULL) d
     ORDER BY t.user_id, t.start_time
    

    user_idで返される値 およびprev_user_id 列は同じです。その「余分な」列を削除するか、クエリを別のクエリで(インラインビューとして)ラップすることで列を並べ替えることができますが、パフォーマンスが低下します。

    SELECT v.user_id
         , v.starttime
         , v.order_number
         , v.tot_dur
      FROM (SELECT t.starttime
                 , t.order_number
                 , IF(t.order_number IS NULL,
                     @tot_dur := IF(@prev_user_id = t.user_id,@tot_dur,0) + t.visit_duration_seconds,
                     @tot_dur := 0
                   ) AS tot_dur
                 , @prev_user_id := t.user_id AS user_id
              FROM visit t
              JOIN (SELECT @tot_dur := 0, @prev_user_id := NULL) d
             ORDER BY t.user_id, t.start_time
           ) v
    

    このクエリは、MySQLが指定された結果セットを返すことが可能であることを示しています。ただし、最適なパフォーマンスを得るには、インラインビュー(別名v)でクエリのみを実行する必要があります。 )、行が取得されるときに、クライアント側で列の並べ替え(user_id列を最初に配置)を処理します。

    他の2つの一般的なアプローチは、半結合と相関サブクエリの使用ですが、これらのアプローチは、大規模なセットを処理する場合により多くのリソースを消費する可能性があります。




    1. SQLスクリプト-#defineに相当するものは存在しますか?

    2. EBSからエフェメラルストレージにデータを移動すると、MySQLクエリのパフォーマンスが向上しますか?

    3. PHPのMySQL日付フィールドのオプションの月または日

    4. SQL Serverデータベースの回復保留状態を修正するにはどうすればよいですか?