MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  ウィンドウ機能フレーム仕様

12.21.3 ウィンドウ機能フレーム仕様

ウィンドウ関数で使用されるウィンドウの定義には、frame 句を含めることができます。 フレームは現在のパーティションのサブセットであり、frame 句はサブセットの定義方法を指定します。

フレームは現在の行に対して決定されます。これにより、現在の行のパーティション内での位置に応じて、フレームをパーティション内で移動できます。 例:

  • パーティションの開始行から現在の行までのすべての行になるようにフレームを定義することで、各行の累積合計を計算できます。

  • 現在の行の両側で N 行を拡張するようにフレームを定義することで、ローリング平均を計算できます。

次のクエリーは、移動フレームを使用して、時間順序付けされた level 値の各グループ内の累積合計、および現在の行とその直前と直後の行から計算されたローリング平均を計算する方法を示しています:

mysql> SELECT
         time, subject, val,
         SUM(val) OVER (PARTITION BY subject ORDER BY time
                        ROWS UNBOUNDED PRECEDING)
           AS running_total,
         AVG(val) OVER (PARTITION BY subject ORDER BY time
                        ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
           AS running_average
       FROM observations;
+----------+---------+------+---------------+-----------------+
| time     | subject | val  | running_total | running_average |
+----------+---------+------+---------------+-----------------+
| 07:00:00 | st113   |   10 |            10 |          9.5000 |
| 07:15:00 | st113   |    9 |            19 |         14.6667 |
| 07:30:00 | st113   |   25 |            44 |         18.0000 |
| 07:45:00 | st113   |   20 |            64 |         22.5000 |
| 07:00:00 | xh458   |    0 |             0 |          5.0000 |
| 07:15:00 | xh458   |   10 |            10 |          5.0000 |
| 07:30:00 | xh458   |    5 |            15 |         15.0000 |
| 07:45:00 | xh458   |   30 |            45 |         20.0000 |
| 08:00:00 | xh458   |   25 |            70 |         27.5000 |
+----------+---------+------+---------------+-----------------+

running_average カラムの場合、最初のカラムの前または最後のカラムの後にフレーム行はありません。 このような場合、AVG() は使用可能な行の平均を計算します。

ウィンドウ関数として使用される集計関数は、次の非集計ウィンドウ関数と同様に、現在の行フレームの行を操作します:

FIRST_VALUE()
LAST_VALUE()
NTH_VALUE()

標準 SQL は、パーティション全体で動作するウィンドウ関数に frame 句を含めないことを指定します。 MySQL では、このような関数の frame 句は許可されますが、無視されます。 これらの関数は、フレームが指定されている場合でもパーティション全体を使用します:

CUME_DIST()
DENSE_RANK()
LAG()
LEAD()
NTILE()
PERCENT_RANK()
RANK()
ROW_NUMBER()

frame 句が指定されている場合、構文は次のとおりです:

frame_clause:
    frame_units frame_extent

frame_units:
    {ROWS | RANGE}

frame 句がない場合、このセクションの後半で説明するように、デフォルトのフレームは ORDER BY 句が存在するかどうかによって異なります。

frame_units 値は、現在の行とフレーム行の関係のタイプを示します:

  • ROWS: フレームは、開始行と終了行の位置によって定義されます。 オフセットは、現在の行番号と行番号の違いです。

  • RANGE: フレームは、値の範囲内の行によって定義されます。 オフセットは、現在の行の値と行の値の違いです。

frame_extent 値は、フレームの開始点と終了点を示します。 フレームの開始のみを指定するか (この場合、現在の行が暗黙的に終了します)、BETWEEN を使用して両方のフレームエンドポイントを指定できます:

frame_extent:
    {frame_start | frame_between}

frame_between:
    BETWEEN frame_start AND frame_end

frame_start, frame_end: {
    CURRENT ROW
  | UNBOUNDED PRECEDING
  | UNBOUNDED FOLLOWING
  | expr PRECEDING
  | expr FOLLOWING
}

BETWEEN 構文では、frame_startframe_end より後にすることはできません。

許可される frame_start および frame_end の値には、次の意味があります:

  • CURRENT ROW: ROWS の場合、バインドは現在の行です。 RANGE の場合、バインドは現在の行のピアです。

  • UNBOUNDED PRECEDING: バインドは最初のパーティション行です。

  • UNBOUNDED FOLLOWING: バインドは最後のパーティション行です。

  • expr PRECEDING: ROWS の場合、バインドは現在の行の前の expr 行です。 RANGE の場合、バインドされるのは、現在の行の値から expr を引いた値を持つ行です。現在の行の値が NULL の場合、バインドされるのは行のピアです。

    expr PRECEDING (および expr FOLLOWING) の場合、expr? パラメータマーカー (プリペアドステートメントで使用)、負でない数値リテラルまたは INTERVAL val unit 形式の時間間隔になります。 INTERVAL 式の場合、val は負でない間隔値を指定し、unit は値を解釈する単位を示すキーワードです。 (許可されている units 指定子の詳細は、セクション12.7「日付および時間関数」DATE_ADD() 関数の説明を参照してください。)

    数値または時間的 expr 上の RANGE には、それぞれ数値式または時間的式上の ORDER BY が必要です。

    有効な expr PRECEDING および expr FOLLOWING インジケータの例:

    10 PRECEDING
    INTERVAL 5 DAY PRECEDING
    5 FOLLOWING
    INTERVAL '2:30' MINUTE_SECOND FOLLOWING
  • expr FOLLOWING: ROWS の場合、バインドは現在の行の後の expr 行です。 RANGE の場合、バインドされるのは、現在の行の値に expr を加えた値を持つ行です。現在の行の値が NULL の場合、バインドされるのは行のピアです。

    expr の許容値については、 expr PRECEDING の説明を参照してください。

次のクエリーは、FIRST_VALUE()LAST_VALUE() および NTH_VALUE() の 2 つのインスタンスを示しています:

mysql> SELECT
         time, subject, val,
         FIRST_VALUE(val)  OVER w AS 'first',
         LAST_VALUE(val)   OVER w AS 'last',
         NTH_VALUE(val, 2) OVER w AS 'second',
         NTH_VALUE(val, 4) OVER w AS 'fourth'
       FROM observations
       WINDOW w AS (PARTITION BY subject ORDER BY time
                    ROWS UNBOUNDED PRECEDING);
+----------+---------+------+-------+------+--------+--------+
| time     | subject | val  | first | last | second | fourth |
+----------+---------+------+-------+------+--------+--------+
| 07:00:00 | st113   |   10 |    10 |   10 |   NULL |   NULL |
| 07:15:00 | st113   |    9 |    10 |    9 |      9 |   NULL |
| 07:30:00 | st113   |   25 |    10 |   25 |      9 |   NULL |
| 07:45:00 | st113   |   20 |    10 |   20 |      9 |     20 |
| 07:00:00 | xh458   |    0 |     0 |    0 |   NULL |   NULL |
| 07:15:00 | xh458   |   10 |     0 |   10 |     10 |   NULL |
| 07:30:00 | xh458   |    5 |     0 |    5 |     10 |   NULL |
| 07:45:00 | xh458   |   30 |     0 |   30 |     10 |     30 |
| 08:00:00 | xh458   |   25 |     0 |   25 |     10 |     30 |
+----------+---------+------+-------+------+--------+--------+

各関数は、現在のフレーム内の行を使用します。この行は、表示されているウィンドウ定義に従って、最初のパーティション行から現在の行に拡張されます。 NTH_VALUE() コールの場合、現在のフレームにはリクエストされた行が常に含まれるわけではありません。このような場合、戻り値は NULL です。

frame 句がない場合、デフォルトのフレームは ORDER BY 句が存在するかどうかによって異なります:

  • ORDER BY を使用: デフォルトのフレームには、現在の行のすべてのピア (ORDER BY 句に従って現在の行と等しい行) を含む、パーティションの開始行から現在の行までの行が含まれます。 デフォルトは、次のフレーム仕様と同等です:

    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  • ORDER BY なし: デフォルトのフレームには、すべてのパーティション行が含まれます (ORDER BY がない場合、すべてのパーティション行はピアであるため)。 デフォルトは、次のフレーム仕様と同等です:

    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

デフォルトのフレームは ORDER BY の有無によって異なるため、ORDER BY をクエリーに追加して決定的な結果を取得すると、結果が変わる可能性があります。 (たとえば、SUM() によって生成される値は変更される可能性があります。) 同じ結果を取得するが、ORDER BY ごとに順序付けするには、ORDER BY が存在するかどうかに関係なく、使用する明示的なフレーム仕様を指定します。

現在の行の値が NULL の場合、フレーム指定の意味は明白ではない可能性があります。 その場合、次の例は様々なフレーム仕様がどのように適用されるかを示しています:

  • ORDER BY X ASC RANGE BETWEEN 10 FOLLOWING AND 15 FOLLOWING

    フレームは NULL で始まり、NULL で停止するため、値が NULL の行のみが含まれます。

  • ORDER BY X ASC RANGE BETWEEN 10 FOLLOWING AND UNBOUNDED FOLLOWING

    フレームは NULL から始まり、パーティションの最後で停止します。 ASC ソートでは NULL 値が最初に配置されるため、フレームはパーティション全体になります。

  • ORDER BY X DESC RANGE BETWEEN 10 FOLLOWING AND UNBOUNDED FOLLOWING

    フレームは NULL から始まり、パーティションの最後で停止します。 DESC ソートでは NULL 値が最後に配置されるため、フレームは NULL 値のみです。

  • ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND UNBOUNDED FOLLOWING

    フレームは NULL から始まり、パーティションの最後で停止します。 ASC ソートでは NULL 値が最初に配置されるため、フレームはパーティション全体になります。

  • ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING

    フレームは NULL で始まり、NULL で停止するため、値が NULL の行のみが含まれます。

  • ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 1 PRECEDING

    フレームは NULL で始まり、NULL で停止するため、値が NULL の行のみが含まれます。

  • ORDER BY X ASC RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING

    フレームはパーティションの先頭から始まり、値が NULL の行で停止します。 ASC ソートでは NULL 値が最初に配置されるため、フレームは NULL 値のみです。


関連キーワード:  関数, フレーム, ORDER, PRECEDING, FOLLOWING, expr, RANGE, ウィンドウ, UNBOUNDED, BETWEEN