ウィンドウ関数
背景
ウィンドウ関数は、組み込み関数の特殊なクラスです。集計関数と同様に、複数の入力行に対して計算を行い、単一のデータ値を取得します。違いは、ウィンドウ関数が「group by」メソッドを使用するのではなく、特定のウィンドウ内で入力データを処理することです。 各ウィンドウ内のデータは、over()句を使用してソートおよびグループ化できます。ウィンドウ関数は各行に対して個別の値を計算します、各グループに対して1つの値を計算するのではなく、この柔軟性により、ユーザーはselect句に追加の列を追加し、結果セットをさらにフィルタリングできます。ウィンドウ関数は、selectリストと句の最も外側の位置にのみ表示できます。クエリの最後に、つまりjoin、where、およびgroup byの操作が実行された後に効果を発揮します。ウィンドウ関数は、トレンドの分析、外れ値の計算、大規模データに対するバケット分析によく使用されます。
使用法
構文
function(args) OVER([partition_by_clause] [order_by_clause] [order_by_clause window_clause])
partition_by_clause ::= PARTITION BY expr [, expr ...]
order_by_clause ::= ORDER BY expr [ASC | DESC] [, expr [ASC | DESC] ...]
PARTITION BY句
Partition By句はGroup Byに似ています。1つ以上の指定された列によって入力行をグループ化します。同じ値を持つ行はグループ化されます。
ORDER BY句
Order By句は、基本的に外側のOrder Byと同じです。入力行の順序を定義します。Partition Byが指定されている場合、Order Byは各パーティショングループ内の順序を定義します。唯一の違いは、OVER句のOrder By n(nは正の整数)が操作なしと同等であるのに対し、外側のOrder Byのnはn番目の列によるソートを示すことです。
例:
この例では、eventsテーブルのdate_and_time列でソートされた、1、2、3などの値を持つid列をselectリストに追加する方法を示します。
SELECT row_number() OVER (ORDER BY date_and_time) AS id,
c1, c2, c3, c4
FROM events;
ウィンドウ句
ウィンドウ句は、操作の行範囲(現在の行に基づく先行および後続の行)を指定するために使用されます。以下の構文をサポートしています: AVG()、COUNT()、FIRST_VALUE()、LAST_VALUE()、およびSUM()。MAX()とMIN()の場合、ウィンドウ句は開始からUNBOUNDED PRECEDINGまでを指定できます。
構文:
ROWS BETWEEN [ { m | UNBOUNDED } PRECEDING | CURRENT ROW] [ AND [CURRENT ROW | { UNBOUNDED | n } FOLLOWING] ]
RANGE BETWEEN [ { m | UNBOUNDED } PRECEDING | CURRENT ROW] [ AND [CURRENT ROW | { UNBOUNDED | n } FOLLOWING] ]
ARRAY_AGG() ウィンドウフレームの制限:
ARRAY_AGG()をウィンドウ関数として使用する場合、RANGEフレームのみがサポートされます。ROWSフレームはサポートされません。例:
-- サポート対象: RANGEフレーム
array_agg(col) OVER (PARTITION BY x ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
-- サポート対象外: ROWSフレーム (エラーが発生します)
array_agg(col) OVER (PARTITION BY x ORDER BY y ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
ウィンドウ関数サンプルテーブル
このセクションでは、サンプルテーブルscoresを作成します。このテーブルを使用して、以下の多くのウィンドウ関数をテストできます。
CREATE TABLE `scores` (
`id` int(11) NULL,
`name` varchar(11) NULL,
`subject` varchar(11) NULL,
`score` int(11) NULL
)
DISTRIBUTED BY HASH(`score`) BUCKETS 10;
INSERT INTO `scores` VALUES
(1, "lily", "math", NULL),
(1, "lily", "english", 100),
(1, "lily", "physics", 60),
(2, "tom", "math", 80),
(2, "tom", "english", 98),
(2, "tom", "physics", NULL),
(3, "jack", "math", 95),
(3, "jack", "english", NULL),
(3, "jack", "physics", 99),
(4, "amy", "math", 80),
(4, "amy", "english", 92),
(4, "amy", "physics", 99),
(5, "mike", "math", 70),
(5, "mike", "english", 85),
(5, "mike", "physics", 85),
(6, "amber", "math", 92),
(6, "amber", NULL, 90),
(6, "amber", "physics", 100);
関数例
このセクションでは、StarRocksでサポートされているウィンドウ関数について説明します。
AVG()
指定されたウィン ドウ内のフィールドの平均値を計算します。この関数はNULL値を無視します。
構文:
AVG([DISTINCT] expr) [OVER (*analytic_clause*)]
DISTINCTはStarRocks v4.0からサポートされています。指定すると、AVG()はウィンドウ内の異なる値のみの平均を計算します。
ウィンドウフレームの制限:
AVG(DISTINCT)をウィンドウ関数として使用する場合、RANGEフレームのみがサポートされます。ROWSフレームはサポートされません。
例
例1: 基本的な使用法
次の例では、株価データを例として使用します。
CREATE TABLE stock_ticker (
stock_symbol STRING,
closing_price DECIMAL(8,2),
closing_date DATETIME
)
DUPLICATE KEY(stock_symbol)
COMMENT "OLAP"
DISTRIBUTED BY HASH(closing_date);
INSERT INTO stock_ticker VALUES
("JDR", 12.86, "2014-10-02 00:00:00"),
("JDR", 12.89, "2014-10-03 00:00:00"),
("JDR", 12.94, "2014-10-04 00:00:00"),
("JDR", 12.55, "2014-10-05 00:00:00"),
("JDR", 14.03, "2014-10-06 00:00:00"),
("JDR", 14.75, "2014-10-07 00:00:00"),
("JDR", 13.98, "2014-10-08 00:00:00")
;
現在の行と、その前後の各行の平均終値を計算します。
select stock_symbol, closing_date, closing_price,
avg(closing_price)
over (partition by stock_symbol
order by closing_date
rows between 1 preceding and 1 following
) as moving_average
from stock_ticker;
出力:
+--------------+---------------------+---------------+----------------+
| stock_symbol | closing_date | closing_price | moving_average |
+--------------+---------------------+---------------+----------------+
| JDR | 2014-10-02 00:00:00 | 12.86 | 12.87500000 |
| JDR | 2014-10-03 00:00:00 | 12.89 | 12.89666667 |
| JDR | 2014-10-04 00:00:00 | 12.94 | 12.79333333 |
| JDR | 2014-10-05 00:00:00 | 12.55 | 13.17333333 |
| JDR | 2014-10-06 00:00:00 | 14.03 | 13.77666667 |
| JDR | 2014-10-07 00:00:00 | 14.75 | 14.25333333 |
| JDR | 2014-10-08 00:00:00 | 13.98 | 14.36500000 |
+--------------+---------------------+---------------+----------------+
例えば、最初の行の12.87500000は、「2014-10-02」(12.86)、その前日「2014-10-01」(null)、およびその翌日「2014-10-03」(12.89)の終値の平均値です。
例2: 全体ウィンドウでのAVG(DISTINCT)の使用
この例では、示例表 scores のデータを使用します。
すべての行で重複しないスコアの平均を計算します。
SELECT id, subject, score,
AVG(DISTINCT score) OVER () AS distinct_avg
FROM test_scores;
出力:
+----+---------+-------+-------------+
| id | subject | score | distinct_avg|
+----+---------+-------+-------------+
| 1 | math | 80 | 85.00 |
| 2 | math | 85 | 85.00 |
| 3 | math | 80 | 85.00 |
| 4 | english | 90 | 85.00 |
| 5 | english | 85 | 85.00 |
| 6 | english | 90 | 85.00 |
+----+---------+-------+-------------+
重複しない平均は85.00です ((80 + 85 + 90) / 3)。
例3: RANGEフレームを持つフレーム付きウィンドウでAVG(DISTINCT)を使用する
この例では、示例表 scores のデータを使用します。
RANGEフレームを使用して、各科目パーティション内で重複しないスコアの平均を計算します。
SELECT id, subject, score,
AVG(DISTINCT score) OVER (
PARTITION BY subject
ORDER BY score
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS distinct_avg
FROM test_scores;
出力:
+----+---------+-------+-------------+
| id | subject | score | distinct_avg|
+----+---------+-------+-------------+
| 1 | math | 80 | 80.00 |
| 3 | math | 80 | 80.00 |
| 2 | math | 85 | 82.50 |
| 5 | english | 85 | 85.00 |
| 4 | english | 90 | 87.50 |
| 6 | english | 90 | 87.50 |
+----+---------+-------+-------------+
各行について、この関数はパーティションの開始から現在の行のスコア値まで(現在の行のスコア値を含む)の重複しないスコアの平均を計算します。
ARRAY_AGG()
ウィンドウ内の値(NULL値を含む)を配列に集約します。オプションの ORDER BY 句を使用して、配列内の要素をソートできます。
この関数はv3.4以降でサポートされています。
ウィンドウフレームの制限:
ウィンドウ関数 としての ARRAY_AGG() は RANGE ウィンドウフレームのみをサポートします。ROWS ウィンドウフレームはサポートされていません。ウィンドウフレームが指定されていない場合、デフォルトの RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW が使用されます。
構文:
ARRAY_AGG([DISTINCT] expr [ORDER BY expr [ASC | DESC]]) OVER([partition_by_clause] [order_by_clause] [window_clause])
パラメータ:
expr: 集約する式。サポートされている任意のデータ型の列にすることができます。DISTINCT: オプション。結果配列から重複する値を削除します。ORDER BY: オプション。配列内の要素の順序を指定します。
戻り値:
ウィンドウ内のすべての値を含むARRAYを返します。
使用上の注意:
- ROWSフレームはサポートされていません。 ウィンドウ関数としてのARRAY_AGG()では、RANGEフレームのみを使用できます。ROWSフレームを使用するとエラーになります。
- NULL値は結果配列に含まれます。
DISTINCTが指定されている場合、重複する値は配列から削除されます。- ARRAY_AGG()内で
ORDER BYが指定されている場合、結果の配列内の要素はそれに応じてソートされます。
例