皆さんこんにちは、私の名前はニンイーです。
今日はレッスン 24: ウィンドウ関数です。
ウィンドウ関数は OLAP (オンライン分析処理) とも呼ばれ、データベース データのリアルタイム分析と処理を実行できます。
ウィンドウ関数はデータアナリストがよく使う構文関数で、大手企業の面接ではほぼ必須の質問となります。
このセクションは高度な内容であり、理解するのが難しいため、効果を確認するにはコンピュータに入力する必要があります。
そうすることでのみ、理解が深まるのです。前回のコースではデータベースのインストール方法を説明しましたが、私のホームページで確認できます~
基本的な文法
<窗口函数> OVER (
[PARTITION BY <用于分组的列名>] -- 可选
[ORDER BY <用于排序的列名>] -- 可选
)
上記の <window function> の位置には、次の 2 つの関数を配置できます。
(1) 集計関数: sum.avg、count、max、min など。
(2) 特別なウィンドウ関数: Rank、dense_rank、row_number など。これについては以下で詳しく説明します。
通常、ウィンドウ関数は select ステートメントに配置されます。
1. 集計機能
ウィンドウ関数はグループ化と並べ替えにも使用され、集計関数 + GROUP BY と同様の効果があります。ただし、ウィンドウ関数によって生成されたレコードは集約されず、データ行ごとに 1 つのレコードが生成されます。
例: [スコア] テーブルで、ID が 7 ~ 10 の生徒を検索し、各生徒の合計スコアを計算して表示します。
SELECT
Sid,
SUM(score) AS "总分"
FROM Scores
WHERE Sid BETWEEN 7 AND 10
GROUP BY Sid;
しかし、ここで問題が発生します。生徒の合計スコアはわかりますが、各科目の具体的なスコアも知りたいのです。これは、上記のステートメントを使用して行うことはできません。
なぜ?
SELECT の後のフィールドがテーブル内の既存の列である場合、この列も GROUP BY 句に含める必要があるためです。
したがって、各科目の具体的なスコアを知りたい場合は、SELECT の後に Cid とスコアの 2 つの列を追加する必要があります。これらの 2 つの列を GROUP BY 句に追加すると、トピックに反します。
この知識点については、講義 15 と 16 で強調しました。ホームページをクリックして詳細を学ぶことができますが、ここでは詳しく説明しません。
同僚に学生の合計スコア、コース番号、スコアを知らせたい場合は、ウィンドウ関数を使用する必要があります。
SELECT
Sid,Cid,score,
SUM(score) OVER (PARTITION BY Sid) AS "总分"
FROM Scores
WHERE Sid BETWEEN 7 AND 10;
補足知識:PARTITION BYの意味
PARTITION BY はパーティションを意味し、GROUP BY と同様です。
PARTITION BY が記述されていない場合は、データ セット全体が 1 つのパーティションに属していることを意味します。
たとえば、上記の SQL ステートメントで PARTITION BY が省略された場合、
SELECT
Sid,Cid,score,
SUM(score) OVER() AS "总分"
FROM Scores
WHERE Sid BETWEEN 7 AND 10;
結果は以下のようになり、生徒全員の合計点が計算されます。
2. 特殊なウィンドウ機能
一般的に使用される特別なウィンドウ関数は次のとおりです。
(1) データランキングの取得:
ROW_NUMBER():同順位のランキングは考慮されません。たとえば、上位 3 つのスコアはすべて 88、88、77 であり、ランキングは 1、2、3 になります。
RANK():ランキングが同点の行がある場合、それらは次にランク付けされた位置を占めます。たとえば、上位 3 つのスコアはすべて 88、88、77 であり、順位は 1、1、3 になります。
DEBSE_RANK():ランク付けされた行が同点の場合、それらは次にランク付けされた位置を占めません。たとえば、上位 3 つのスコアはすべて 88、88、77 であり、順位は 1、1、2 になります。
例:スコア表で、ID が 7 ~ 10 の生徒を検索し、上位から下位までのランキングを計算します。
SELECT *,
ROW_NUMBER() OVER(
ORDER BY score DESC
) AS "排名"
FROM Scores
WHERE Sid BETWEEN 7 AND 10;
上記では ROW_NUMBER() ウィンドウ関数が使用されており、「Ranking」列が追加されていることがわかります。ROW_NUMBER() を RANK() に置き換えると、戻り結果は次のようになります。
(2) 最初または最後の場所を取得します。
FIRST_VALUE(<列名>) : 1 位を取得します。
LAST_VALUE(<列名>) : 最後の値を取得します。
例:スコア表で、ID が 7 ~ 10 の生徒を検索し、各生徒の最高スコアを取得します。
SELECT *,
FIRST_VALUE(score) OVER(
PARTITION BY Sid
ORDER BY score DESC
) AS "最高成绩"
FROM Scores
WHERE Sid BETWEEN 7 AND 10;
(3) オフセット機能:
LEAD(<列名>,<値 n>) : 現在の行から n 行下方向のデータ オフセットにアクセスします。
LAG(<列名>,<値 n>) : 現在の行から n 行のデータ オフセットにアクセスします。
NTH_VALUE(<列名>,<値 n>) : 結果セットの N 行目からデータを取得します。
(4) 分配関数:
CUME_DIST() : 現在のランク値/グループ内の合計行数以下のグループ内の行数。
PERCENT_RANK() : 列の各行のランキングのパーセンテージを返します。各行は、式 (rank-1) / (rows-1) に従って計算されます。
NTILE(<Number n>) : 結果セット全体を n 個のグループに分割し、特定のデータがどのグループに割り当てられているかを示します。
宿題:スコアのオフセット関数と分布関数を検証し、どのような結果が返されるかを確認します。
例:以下の行 2 のオフセット スコアを取得します。
SELECT *,
LEAD(score,2) OVER(
ORDER BY score DESC
) AS "获取下面第2行score值"
FROM Scores
WHERE Sid BETWEEN 7 AND 10;
SQL の入門コースから上級コースまでが終了しました。今後も、ビュー、インデックス、同時実行性、デッドロック、トリガー、イベント、トランザクション、ストアド プロシージャなどを含む高度な SQL コースを公開し続ける予定です。
録画授業とライブ授業も続きます~