ウィンドウ関数
背景
ウィンドウ関数は、特別なクラスの組み込み関数です。集計関数と同様に、複数の入力行に対して計算を行い、単一のデータ値を取得します。違いは、ウィンドウ関数が特定のウィンドウ内で入力データを処理することで、「group by」メソッドを使用しないことです。各ウィンドウ内のデータは、over()句を使用してソートおよびグループ化できます。ウィンドウ関数は、各行に対して個別の値を計算し、グループごとに1つの値を計算するので はありません。この柔軟性により、ユーザーはselect句に追加の列を追加し、結果セットをさらにフィルタリングできます。ウィンドウ関数は、selectリストおよび句の最外部の位置にのみ表示できます。クエリの最後、つまりjoin、where、およびgroup by操作が実行された後に効果を発揮します。ウィンドウ関数は、トレンドの分析、外れ値の計算、大規模データのバケット分析によく使用されます。
使用法
構文
function(args) OVER(partition_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は各Partitionグループ内の順序を定義します。唯一の違いは、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] ]
ウィンドウ関数サンプルテーブル
このセクションでは、サンプルテーブル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(expr) [OVER (*analytic_clause*)]
例:
以下の例では、株式データを例に使用します。
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)の平均値です。
COUNT()
指定されたウィンドウ内で条件を満たす行の総数を計算します。
構文:
COUNT(expr) [OVER (analytic_clause)]
例:
現在の行からmathパーティション内の最初の行までの間で、90を超えるmathスコアの出現回数をカウントします。この例では、サンプルテーブルscoresのデータを使用します。
select *,
count(score)
over (
partition by subject
order by score
rows between unbounded preceding and current row
) as 'score_count'
from scores where subject in ('math') and score > 90;
+------+-------+---------+-------+-------------+
| id | name | subject | score | score_count |
+------+-------+---------+-------+-------------+
| 6 | amber | math | 92 | 1 |
| 3 | jack | math | 95 | 2 |
+------+-------+---------+-------+-------------+
DENSE_RANK()
DENSE_RANK()関数はランキングを表すために使用されます。RANK()とは異なり、DENSE_RANK()は空白のない番号を持ちます。例えば、1位が2つある場合、DENSE_RANK()の3番目の番号は2のままですが、RANK()の3番目の番号は3になります。
構文:
DENSE_RANK() OVER(partition_by_clause order_by_clause)
例:
以下の例では、mathスコアのランキングを示しています(降順)。この例では、サンプルテーブルscoresのデータを使用します。
select *,
dense_rank()
over (
partition by subject
order by score desc
) as `rank`
from scores where subject in ('math');
+------+-------+---------+-------+------+
| id | name | subject | score | rank |
+------+-------+---------+-------+------+
| 3 | jack | math | 95 | 1 |
| 6 | amber | math | 92 | 2 |
| 2 | tom | math | 80 | 3 |
| 4 | amy | math | 80 | 3 |
| 5 | mike | math | 70 | 4 |
| 1 | lily | math | NULL | 5 |
+------+-------+---------+-------+------+
結果データには、スコアが80の行が2つあります。これらはすべて3位です。次のスコア70の順位は4位です。これにより、DENSE_RANK()は空白のない番号を持つことが示されています。