1.基本的な考え方
MySQLは8.0以降、ウィンドウ関数をサポートしています。この関数は、ほとんどの商用データベースと一部のオープンソースデータベースで長い間サポートされており、一部は分析関数とも呼ばれます。
概念:
ウィンドウの概念はレコードセットとして理解できます。ウィンドウ関数は、特定の条件を満たすレコードセットに対して実行される特別な関数です。各レコードについて、このウィンドウで関数を実行する必要があります。一部の関数はレコードによって異なります。ウィンドウサイズはすべて固定されています。これは静的ウィンドウです。一部の関数は、異なるウィンドウに対応する異なるレコードです。この種の動的に変化するウィンドウは、スライディングウィンドウと呼ばれます。
ウィンドウ関数と集計関数:
- 集計関数は、複数のレコードを1つに集約することです。
- ウィンドウ関数は、すべてのレコード、実行されるレコードの数、またはいくつのレコードに対して実行されます。
- 集計関数は、ウィンドウ関数にも使用できます。
2.基本フォーマット
基本構文:<ウィンドウ関数> over(節)
-
<ウィンドウ関数>の位置には、専用のウィンドウ関数(rank()、percent_rank()、dense_rank()など)または集計関数(sum()、avg()、max()など)を配置できます。
-
ウィンドウ関数は、where句またはgroup by句の結果を操作するため、原則として、SELECT句でのみ記述されます。
-
Overは、実行する関数のウィンドウ範囲を指定するために使用されます。句が空の場合、ウィンドウにはWHERE条件を満たすすべての行が含まれ、ウィンドウ関数はすべての行に基づいて計算されます。
-
句が空でない場合、ウィンドウを設定するために次の4つの構文がサポートされます。
window_name:ウィンドウにエイリアスを割り当てます。ウィンドウのSQLがより多く含まれている場合は、エイリアスの使用がより読みやすくなる可能性があります。
SELECT `姓名`, `班级`, `人气`, rank() over w1 AS rak FROM `民工漫班级` window w1 AS ( PARTITION BY `班级` ORDER BY `人气` DESC );
結果:
パーティション句:ウィンドウによってグループ化されたフィールド。ウィンドウ関数は別のパケットで実行されます。
order by句:ウィンドウ関数によってソートされるフィールドには、ソートされたレコードの順序に従って番号が付けられます。
フレーム句:フレームは現在のパーティションのサブセットです。この句はサブセットのルールを定義するために使用されます。通常、スライディングウィンドウとして使用されます。(この記事では紹介されていません)
新しく作成された移民労働者クラステーブルを操作するために使用されます:
SELECT
*,
RANK() over ( PARTITION BY `班级` ORDER BY `人气` DESC ) AS ranking
FROM
`民工漫班级`;
# PARTITION BY `班级`:按班级分组(使用group by会改变表的行数,一个类别只保留一行;partition by则不会减少表的行数)
# ORDER BY `人气` DESC:对按班级分组后的结果按人气降序排名,名次作为字段 ranking
結果を取得します:
3、mysqlウィンドウ関数
機能部門:
関数に応じて、MySQLでサポートされているウィンドウ関数は次のカテゴリに分類できます。
- シーケンス番号関数:ROW_NUMBER()、RANK()、DENSE_RANK()
- 分布関数:PERCENT_RANK()、CUME_DIST()、PERCENT_RANK()
- 関数の前後:LAG(expr、n)、LEAD(expr、n)
- ヘッド関数とテール関数:FIRST_VALUE(expr)、LAST_VALUE(expr)
- その他の関数:NTH_VALUE(expr、n)、NTILE(n)
個別に紹介します。
シーケンス番号関数:ROW_NUMBER()、RANK()、DENSE_RANK()
たとえば、上記の移民労働者の男性クラスの表を使用して、次の3つの関数で人気順に並べ替えています。
SELECT
*,
RANK() over ( ORDER BY `人气` DESC ) AS `rank` ,
DENSE_RANK() over ( ORDER BY `人气` DESC ) AS `dense_rank` ,
ROW_NUMBER() over ( ORDER BY `人气` DESC ) AS `row_number`
FROM
`民工漫班级`;
結果:クラスをグループ化するためのパーティションがなくなりました
これから私達は見ることができます:
- RANK():並べて並べ替え、繰り返されるシーケンス番号をスキップ-1、1、3
- DENSE_RANK():並列ソート、繰り返されるシーケンス番号をスキップしない-1、1、2
- ROW_NUMBER():順次ソート-1、2、3;行番号と同等。
分布関数:PERCENT_RANK()、CUME_DIST()
パーセンタイルランク()
目的:前のRANK()関数に関連して、各行は次の式に従って計算されます:(rank-1)/(rows-1)、ここで、rankはRANK()関数によって生成されたシーケンス番号であり、行は現在のウィンドウのレコードの合計行この関数を使用して、クォンタイルを計算できます。
例を示し続けます(実際の予期しないアプリケーションシナリオ):
SELECT
*,
RANK() OVER w AS rankNo,
PERCENT_RANK() OVER w AS percent_rankNo
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `人气` DESC );
結果:
ルフィの場合、percent_rankNo =(rank-1)/(rows-1)=(3-1)/(10-1)= 0.22222222……
CUME_DIST()
目的:現在のランク値以下のグループ内の行数/グループ内の行の総数
例:現在の人気以下の割合(または、人生で非常に一般的に使用されている上位の誰かの数パーセント)をクエリします
SELECT
*,
CUME_DIST() OVER w AS cdt
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `人气` DESC );
結果:
関数の前後:LAG(expr、n)、LEAD(expr、n)
目的:現在の行の最初のn行(LAG(expr、n))または最後のn行(LEAD(expr、n))のexprの値を返します(現在の行の原点に基づく)
例:これは人生でかなり一般的であるはずです
SELECT
*,
`我的前面一名人气` - `人气` AS `我和前面一名的差距`,
`人气` - `后面一名人气` AS `我甩开后面一名多少差距`
FROM
(
SELECT
*,
LAG( `人气`, 1 ) OVER w AS `我的前面一名人气`,# 取前面第一行的人气值
LEAD( `人气`, 1 ) OVER w AS `后面一名人气` # 取后面第一行的人气值
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `人气` DESC )
) t;
結果:
愛染の最初のラインは人気が90でギャップが2のルフィです。次のラインはサスケで、彼に人気を残しています。
ヘッド関数とテール関数:FIRST_VALUE(expr)、LAST_VALUE(expr)
目的:最初の(FIRST_VALUE(expr))または最後の(LAST_VALUE(expr))exprの値を返します
例:現在の人気の時点で、人気ランキングによると、最初と最後の場所は何ですか(降順で、最後の場所は自分である必要があります)
SELECT
*,
FIRST_VALUE( `人气` ) OVER w AS `当前第一人气值`,
LAST_VALUE( `人气` ) OVER w AS `当前倒数第一人气值`
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `人气` DESC );
結果:
その他の関数:NTH_VALUE(expr、n)、NTILE(n)
NTH_VALUE(expr、n)
目的:ウィンドウ内のN番目のexprの値を返します。exprは式または列名にすることができます。
例:現在の人気の時点で、各キャラクターの人気の2番目、4番目、6番目の人気値を表示します
SELECT
*,
NTH_VALUE( `人气`, 2 ) OVER w AS `第二人气值`,
NTH_VALUE( `人气`, 4 ) OVER w AS `第四人气值`,
NTH_VALUE( `人气`, 6 ) OVER w AS `第六人气值`
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `人气` DESC );
結果:
NTILE(n)
目的:パーティション内の順序付けられたデータをnレベルに分割し、レベル数を記録します
例:
SELECT
*,
ROW_NUMBER() OVER w AS 'row_number',
NTILE( 2 ) OVER w AS 'ntile2',
NTILE( 4 ) OVER w AS 'ntile4'
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `人气` );
結果:
第4に、集約関数をウィンドウ関数として使用します
目的:ウィンドウ内の各レコードに集計関数(SUM()、AVG()、MAX()、MIN()、COUNT())を動的に適用し、指定されたウィンドウでさまざまな集計関数値を動的に計算します
例:通常の使用:
SELECT
*,
sum( `人气` ) AS current_sum,
avg( `人气` ) AS current_avg,
count( `人气` ) AS current_count,
max( `人气` ) AS current_max,
min( `人气` ) AS current_min
FROM
`民工漫班级`;
結果:
ウィンドウ関数として、学生番号で並べ替えます。
SELECT
*,
sum( `人气` ) over w AS current_sum,
avg( `人气` ) over w AS current_avg,
count( `人气` ) over w AS current_count,
max( `人气` ) over w AS current_max,
min( `人气` ) over w AS current_min
FROM
`民工漫班级` WINDOW w AS ( ORDER BY `学号` );
結果:
current_sumを例にとると、各行のcurrent_sumの人气
値は、上のすべての行の値の合計です。
この記事は主に
「MySql8.0リファレンスマニュアル」を参照しています。