9. /34
ROWS/RANGE
? パーティション内の開始点と終了点を指定することで、パーティ
ション内の行をさらに制限します。
? 前後の行は、ORDER BY 句での順序に基づいて定義されます。
ROWS
? 現在行の前または後にある固定数の行を指定することにより、パー
ティション内の行が限定されます。
RANGE
? 現在行の値を基準とする値の範囲を指定することにより、パーティ
ション内の行を論理的に限定します。
? ORDER BY 句を指定し、ROWS/RANGEを省略した場合、以下
の規定値が使用されます。
※ ROWS/RANGE句の指定を受け入れることができるウィンドウ関数に対して
のみ適用されます。(順位付け関数は ROWS/RANGE を受け入れないため、
適用されません)
9
ウィンドウ関数の基本
RANGE UNBOUNDED PRECEDING AND CURRENT ROW
10. /34
ROWS/RANGE
? 基本的な構文
パーテーション内の行セットをAからBの範囲内に絞ります。
AとBの書き方のパターン
UNBOUNDED PRECEDING
? 最初の行。開始位置としてのみ指定可能。
[n] PRECEDING
? 現在の行からみてn行前の行。 RANGEでは指定不可。
CURRENT ROW
? 現在の行 (ROWS の場合) または、現在の値 (RANGE の場合)
[n] FOLLOWING
? 現在の行からみてn行後の行RANGEでは指定不可。
UNBOUNDED FOLLOWING
? 最後の行。終了位置としてのみ指定可能。
10
ウィンドウ関数の基本
ROWS BETWEEN A AND B / RANGE BETWEEN A AND B
参考
12. /34
ROWS/RANGE
? 基本的な構文
パーテーション内の行セットをAからBの範囲内に絞ります。
現在行が最初の行の場合のROWS句で指定した範囲のイメージ
※ 前述のスライドの①②③でのイメージ
12
ウィンドウ関数の基本
ROWS BETWEEN A AND B / RANGE BETWEEN A AND B
No. 営業担当 売上日 売上額
1 Suzuki 2023/2/1 120
2 Suzuki 2023/2/2 200
3 Suzuki 2023/2/5 90
4 Suzuki 2023/2/6 90
5 Suzuki 2023/2/7 110
6 Suzuki 2023/2/8 40
7 Suzuki 2023/2/9 100
???
現在行→
※関数を実行
している行
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW ???①
ROWS BETWEEN 1 PRECEDING
AND 2 FOLLOWING ???②
ROWS BETWEEN 1 PRECEDING
AND 1 PRECEDING ???③
②や③の先頭行より前が開始位置の
場合の関数の実行結果
②???NULLとなる
③???先頭行(現在行と同じ行)から2
行後
の行(No.3の行)を範囲とした
関数の
実行結果となる
参考
13. /34
ROWS/RANGE
? 基本的な構文
パーテーション内の行セットをAからBの範囲内に絞ります。
現在行が2行目の場合のROWS句で指定した範囲のイメージ
※ 前述のスライドの①②③でのイメージ
13
ウィンドウ関数の基本
ROWS BETWEEN A AND B / RANGE BETWEEN A AND B
No. 営業担当 売上日 売上額
1 Suzuki 2023/2/1 120
2 Suzuki 2023/2/2 200
3 Suzuki 2023/2/5 90
4 Suzuki 2023/2/6 90
5 Suzuki 2023/2/7 110
6 Suzuki 2023/2/8 40
7 Suzuki 2023/2/9 100
???
現在行→
※関数を実行
している行
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW ???①
ROWS BETWEEN 1 PRECEDING
AND 2 FOLLOWING ???②
ROWS BETWEEN 1 PRECEDING
AND 1 PRECEDING ???③
参考
14. /34
ROWS/RANGE
? 基本的な構文
パーテーション内の行セットをAからBの範囲内に絞ります。
現在行が3行目の場合のROWS句で指定した範囲のイメージ
※ 前述のスライドの①②③でのイメージ
14
ウィンドウ関数の基本
ROWS BETWEEN A AND B / RANGE BETWEEN A AND B
No. 営業担当 売上日 売上額
1 Suzuki 2023/2/1 120
2 Suzuki 2023/2/2 200
3 Suzuki 2023/2/5 90
4 Suzuki 2023/2/6 90
5 Suzuki 2023/2/7 110
6 Suzuki 2023/2/8 40
7 Suzuki 2023/2/9 100
???
現在行→
※関数を実行
している行
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW ???①
ROWS BETWEEN 1 PRECEDING
AND 2 FOLLOWING ???②
ROWS BETWEEN 1 PRECEDING
AND 1 PRECEDING ???③
参考
15. /34
ROWS/RANGE
? 基本的な構文
パーテーション内の行セットをAからBの範囲内に絞ります。
現在行が4行目の場合のROWS句で指定した範囲のイメージ
15
ウィンドウ関数の基本
ROWS BETWEEN A AND B / RANGE BETWEEN A AND B
No. 営業担当 売上日 売上額
1 Suzuki 2023/2/1 120
2 Suzuki 2023/2/2 200
3 Suzuki 2023/2/5 90
4 Suzuki 2023/2/6 90
5 Suzuki 2023/2/7 110
6 Suzuki 2023/2/8 40
7 Suzuki 2023/2/9 100
???
現在行→
※関数を実行
している行
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW ???①
ROWS BETWEEN 1 PRECEDING
AND 2 FOLLOWING ???②
ROWS BETWEEN 1 FOLLOWING
AND 3 FOLLOWING
ROWS BETWEEN 1 PRECEDING
AND 1 PRECEDING ???③
参考
16. /34
ウィンドウ関数の基本
16
ウィンドウ関数の種類
カテゴリ 使用例 関数例
順位付け関数 Window毎に連番を振る ROW_NUMBER、RANK、
DENSE_RANK など
集計関数 累積集計を計算する COUNT、SUM、AVG、MIN、
MAX など
分析関数 前後のレコードを取得
する
LAG、LEAD、FIRST_VALUE、
LAST_VALUE など
NEXT VALUE FOR ※ シーケンス オブジェクトからシーケンス番号を生成する関
数であり、今回は割愛します。
22. /34
ウィンドウ関数の基本
22
分析関数
SELECT ID,部品名, 調達先名, 単価,
LAG(単価,1) OVER(PARTITION BY 部品名 ORDER BY 単価),
LEAD(単価,1) OVER(PARTITION BY 部品名 ORDER BY 単価),
FIRST_VALUE(単価) OVER(PARTITION BY 部品名 ORDER BY 単価),
LAST_VALUE(単価) OVER(PARTITION BY 部品名 ORDER BY 単価)
FROM
部品調達単価
ID 部品名 調達先名 単価 LAG LEAD FIRST_VALUE LAST_VALUE
1 部品A B社 100 NULL 140 100 100
2 部品A A社 140 100 NULL 100 140
3 部品B B社 200 NULL NULL 200 200
5 部品C B社 180 NULL 200 180 180
4 部品C A社 200 180 NULL 180 200
参考
23. /34
GROUP BYとの違い
23
? GROUP BYを使った集計関数との違いは?
部品名 調達先名 単価
部品A B社 100
部品A A社 140
部品B B社 200
部品C A社 200
部品C B社 180
部品調達単価
GROUP BYのイメージ
部品名 平均
部品A 120
部品B 200
部品C 190
部品ごとの平均単価を集計
部品名 調達先名 単価 平均
部品A B社 100 120
部品A A社 140 120
部品B B社 200 200
部品C A社 200 190
部品C B社 180 190
GROUP BYで集約し、計
算
ウィンドウ関数のイメージ
SELECT
部品名, 調達先名, 単価,
AVG(単価) OVER(PARTITION BY 部品名) AS 平均
FROM
部品調達単価
部品ごとの平均単価も取得
PARTITION BYで分割し
た範囲の集計結果を取得
SELECT
部品名, AVG(単価) AS 平均
FROM
部品調達単価
GROUP BY
部品名
参考
24. /34
GROUP BYとの違い
24
? ウィンドウ関数と同じクエリを GROUP BY で表現すると。。。
SELECT
単価.部品名, 単価.調達先名, 単価.単価, 平均単価.平均
FROM 部品調達単価 AS 単価
INNER JOIN (
SELECT
部品名, AVG(単価) AS 平均
FROM
部品調達単価
GROUP BY
部品名
) AS 平均単価
ON 単価.部品名 = 平均単価.部品名
SELECT
部品名, 調達先名, 単価,
AVG(単価) OVER(PARTITION BY 部品名) AS 平均
FROM
部品調達単価
参考
29. /34
WINDOW句の紹介
29
MSドキュメントの「一般的な注釈」の主な点を解説
? WINDOW 句では、複数の名前付きウィンドウを定義できます。
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER win2 AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win1 AS (ORDER BY SalesOrderID, ProductID),
win2 AS (PARTITION BY SalesOrderID ORDER BY SalesOrderID, ProductID)
Win1とwin2の複数を定義
30. /34
WINDOW句の紹介
30
MSドキュメントの「一般的な注釈」の主な点を解説
? OVER 句の名前付きウィンドウに追加コンポーネントを追加するには、後ろに追加の仕様が
続く window_name を使用します。 しかし、WINDOW 句で指定されたプロパティを OVER
句で再定義することはできません。
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER(win1 PARTITION BY SalesOrderID) AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win1 AS (ORDER BY SalesOrderID, ProductID)
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER(win1 PARTITION BY SalesOrderID ORDER BY SalesOrderID DESC) AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win1 AS (ORDER BY SalesOrderID, ProductID)
ORDER BYはwin1で定義済
PARTITION BYを追加
31. /34
WINDOW句の紹介
31
MSドキュメントの「一般的な注釈」の主な点を解説
? クエリで複数のウィンドウが使用されている場合、ある名前付きウィンドウで、
window_name を使用して別の名前付きウィンドウを参照できます。 この場合、参照される
window_name は、参照元ウィンドウのウィンドウ定義で指定する必要があります。 ある
ウィンドウで定義されているウィンドウ コンポーネントは、それを参照する別のウィンドウ
では再定義できません。
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER win2 AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win1 AS (ORDER BY SalesOrderID, ProductID),
win2 AS (win1 PARTITION BY SalesOrderID)
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER win2 AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win1 AS (ORDER BY SalesOrderID, ProductID),
win2 AS (win1 PARTITION BY SalesOrderID ORDER BY SalesOrderID DESC, ProductID)
ORDER BYはwin1で定義済
win2でwin1を参照
32. /34
WINDOW句の紹介
32
MSドキュメントの「一般的な注釈」の主な点を解説
? ウィンドウ句でウィンドウが定義されている順序に基づいて、前方および後方のウィンドウ
参照が許可されます。 つまり、ウィンドウでは、定義されている順序に関係なく、
reference_window_name として、その一部である <window_expression> で定義されている
他のウィンドウを使用できます。 循環参照、および単一ウィンドウでの複数のウィンドウ参
照の使用は許可されません。
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER win3 AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win3 AS (win2),
win1 AS (ORDER BY SalesOrderID, ProductID),
win2 AS (win1 PARTITION BY SalesOrderID)
SELECT SalesOrderID AS OrderNumber, ProductID,
OrderQty AS Qty,
SUM(OrderQty) OVER win1 AS Total,
AVG(OrderQty) OVER win3 AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664)
AND ProductID LIKE '71%'
WINDOW
win3 AS (win2 win1),
win1 AS (ORDER BY SalesOrderID, ProductID),
win2 AS (PARTITION BY SalesOrderID)
後方で定義したwin2を参照
複数のウィンドウ参照
34. /34
WINDOW句の使用例
WINDOW句を使わない従来の記法
例:営業担当ごとの売上推移データ(日ごとと累積の売上額)を取
得する。
WINDOW句を使用した記法
SELECT 営業担当, 売上日, 売上額,
SUM(売上額) OVER (PARTITION BY 営業担当 ORDER BY 売上日, 売上ID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 累積売上額
FROM 売上 ORDER BY 営業担当, 売上日, 売上ID
参考
SELECT 営業担当, 売上日, 売上額,
SUM(売上額) OVER 累積条件 AS 累積売上額
FROM 売上
WINDOW 累積条件 AS (PARTITION BY 営業担当 ORDER BY 売上日, 売上ID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
ORDER BY 営業担当, 売上日, 売上ID
35. /34
WINDOW句の使用例
35
WINDOW句を使わない従来の記法
例:月ごとに直近3カ月の売上の合計と移動平均を取得する。
年月 売上額
2022年10月 100
2022年11月 200
2022年12月 300
2023年01月 200
2023年02月 400
2023年03月 200
年月 売上額
直近3ヶ月の
合計
直近3ヶ月の
移動平均
2022年10月 100 100 100
2022年11月 200 300 150
2022年12月 300 600 200
2023年01月 200 700 233
2023年02月 400 900 300
2023年03月 200 800 266
売上テーブル 月ごとの直近3カ月の売上合計と移動平均
SELECT *,
SUM(売上額) OVER(ORDER BY 年月 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS 直近3ヶ月の合計,
AVG(売上額) OVER(ORDER BY 年月 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS 直近3ヶ月の移動平均
FROM 売上
ORDER BY 年月
参考
36. /34
WINDOW句の使用例
36
WINDOW句を使わない従来の記法
例:月ごとに直近3カ月の売上の合計と移動平均を取得する。
WINDOW句を使用した記法
SELECT *,
SUM(売上額) OVER(ORDER BY 年月 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS 直近3ヶ月の合計,
AVG(売上額) OVER(ORDER BY 年月 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS 直近3ヶ月の移動平均
FROM 売上
ORDER BY 年月
参考
SELECT *,
SUM(売上額) OVER 直近3か月 AS 直近3ヶ月の合計,
AVG(売上額) OVER 直近3か月 AS 直近3ヶ月の移動平均
FROM 売上
WINDOW 直近3か月 AS (ORDER BY 年月 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
ORDER BY 年月