35 KiB
slug | sidebar_position | sidebar_label |
---|---|---|
/ja/sql-reference/aggregate-functions/parametric-functions | 38 | Parametric |
パラメトリック集計関数
いくつかの集計関数は、引数カラム(圧縮のために使用)だけでなく、初期化のためのパラメータのセットを受け入れることができます。構文は、1組ではなく2組の括弧を使用します。1つはパラメータ用で、もう1つは引数用です。
histogram
順応型ヒストグラムを計算します。正確な結果は保証されません。
histogram(number_of_bins)(values)
この関数は、A Streaming Parallel Decision Tree Algorithmを使用します。ヒストグラムのビンの境界は新しいデータが関数に入ると調整されます。一般的な場合、ビンの幅は等しくありません。
引数
values
— 入力値を結果する式。
パラメータ
number_of_bins
— ヒストグラム内のビンの数の上限。関数は自動的にビンの数を計算します。指定されたビンの数に達しようとしますが、失敗した場合は少ないビンを使用します。
返される値
-
[(lower_1, upper_1, height_1), ... (lower_N, upper_N, height_N)]
lower
— ビンの下限。upper
— ビンの上限。height
— ビンの計算された高さ。
例
SELECT histogram(5)(number + 1)
FROM (
SELECT *
FROM system.numbers
LIMIT 20
)
┌─histogram(5)(plus(number, 1))───────────────────────────────────────────┐
│ [(1,4.5,4),(4.5,8.5,4),(8.5,12.75,4.125),(12.75,17,4.625),(17,20,3.25)] │
└─────────────────────────────────────────────────────────────────────────┘
bar関数を使用してヒストグラムを視覚化することができます。例えば:
WITH histogram(5)(rand() % 100) AS hist
SELECT
arrayJoin(hist).3 AS height,
bar(height, 0, 6, 5) AS bar
FROM
(
SELECT *
FROM system.numbers
LIMIT 20
)
┌─height─┬─bar───┐
│ 2.125 │ █▋ │
│ 3.25 │ ██▌ │
│ 5.625 │ ████▏ │
│ 5.625 │ ████▏ │
│ 3.375 │ ██▌ │
└────────┴───────┘
この場合、ヒストグラムビンの境界を知らないことを覚えておく必要があります。
sequenceMatch
シーケンスにパターンに一致するイベントチェーンが含まれているかどうかをチェックします。
構文
sequenceMatch(pattern)(timestamp, cond1, cond2, ...)
:::note 同じ秒に発生するイベントは、結果に影響を与える不明な順序でシーケンス内に存在する可能性があります。 :::
引数
-
timestamp
— 時間データを含んでいると見なされるカラム。一般的なデータ型はDate
とDateTime
です。また、サポートされているUIntデータ型のいずれかを使用することもできます。 -
cond1
,cond2
— イベントチェーンを記述する条件。データ型:UInt8
。最大32の条件引数を渡すことができます。関数は、これらの条件で説明されているイベントのみ考慮します。シーケンスに条件で説明されていないデータが含まれている場合、関数はそれらをスキップします。
パラメータ
pattern
— パターン文字列。パターン構文を参照してください。
返される値
- パターンが一致する場合は1。
- パターンが一致しない場合は0。
型:UInt8
。
パターン構文
-
(?N)
— 位置N
の条件引数に一致します。条件は[1, 32]
の範囲で番号が付けられています。たとえば、(?1)
はcond1
パラメータに渡された引数に一致します。 -
.*
— 任意の数のイベントに一致します。このパターン要素に一致するために条件引数を必要としません。 -
(?t operator value)
— 2つのイベントを隔てる秒数を設定します。たとえば、パターン(?1)(?t>1800)(?2)
は1800秒以上離れて発生するイベントに一致します。これらのイベントの間に任意の数のイベントが存在することができます。>=
,>
,<
,<=
,==
演算子を使用できます。
例
t
テーブル内のデータを考えます:
┌─time─┬─number─┐
│ 1 │ 1 │
│ 2 │ 3 │
│ 3 │ 2 │
└──────┴────────┘
クエリを実行します:
SELECT sequenceMatch('(?1)(?2)')(time, number = 1, number = 2) FROM t
┌─sequenceMatch('(?1)(?2)')(time, equals(number, 1), equals(number, 2))─┐
│ 1 │
└───────────────────────────────────────────────────────────────────────┘
関数は、2番目のイベントが1に続くイベントチェーンを発見しました。その間の3番はイベントとして記述されていないため、スキップされました。例で示されたイベントチェーンを検索するときにこの番号を考慮に入れたい場合は、そのための条件を設定する必要があります。
SELECT sequenceMatch('(?1)(?2)')(time, number = 1, number = 2, number = 3) FROM t
┌─sequenceMatch('(?1)(?2)')(time, equals(number, 1), equals(number, 2), equals(number, 3))─┐
│ 0 │
└──────────────────────────────────────────────────────────────────────────────────────────┘
この場合、関数はパターンに一致するイベントチェーンを見つけられませんでした。なぜなら、3のイベントが1と2の間に発生したからです。同じ場合に4の番号が条件としてチェックされた場合、シーケンスはパターンに一致します。
SELECT sequenceMatch('(?1)(?2)')(time, number = 1, number = 2, number = 4) FROM t
┌─sequenceMatch('(?1)(?2)')(time, equals(number, 1), equals(number, 2), equals(number, 4))─┐
│ 1 │
└──────────────────────────────────────────────────────────────────────────────────────────┘
参照
sequenceCount
パターンに一致したイベントチェーンの数をカウントします。関数は重ならないイベントチェーンを検索します。現在のチェーンが一致した後に次のチェーンの検索を開始します。
:::note 同じ秒に発生するイベントは、結果に影響を与える不明な順序でシーケンス内に存在する可能性があります。 :::
構文
sequenceCount(pattern)(timestamp, cond1, cond2, ...)
引数
-
timestamp
— 時間データを含んでいると見なされるカラム。一般的なデータ型はDate
とDateTime
です。また、サポートされているUIntデータ型のいずれかを使用することもできます。 -
cond1
,cond2
— イベントチェーンを記述する条件。データ型:UInt8
。最大32の条件引数を渡すことができます。関数は、これらの条件で説明されているイベントのみ考慮します。シーケンスに条件で説明されていないデータが含まれている場合、関数はそれらをスキップします。
パラメータ
pattern
— パターン文字列。パターン構文を参照してください。
返される値
- 一致した重ならないイベントチェーンの数。
型:UInt64
例
t
テーブル内のデータを考えます:
┌─time─┬─number─┐
│ 1 │ 1 │
│ 2 │ 3 │
│ 3 │ 2 │
│ 4 │ 1 │
│ 5 │ 3 │
│ 6 │ 2 │
└──────┴────────┘
任意の他の番号がそれらの間に存在しても、番号1の後に番号2が何回発生するかを数えます:
SELECT sequenceCount('(?1).*(?2)')(time, number = 1, number = 2) FROM t
┌─sequenceCount('(?1).*(?2)')(time, equals(number, 1), equals(number, 2))─┐
│ 2 │
└─────────────────────────────────────────────────────────────────────────┘
参照
windowFunnel
スライディングタイムウィンドウでイベントチェーンを検索し、チェーンから発生したイベントの最大数を計算します。
関数は次のアルゴリズムに従って動作します:
-
関数はチェーンの最初の条件をトリガーするデータを検索し、イベントカウンターを1に設定します。これはスライディングウィンドウが始まる瞬間です。
-
ウィンドウ内でチェーンのイベントが順次発生する場合、カウンターはインクリメントされます。イベントのシーケンスが中断された場合、カウンターはインクリメントされません。
-
データに異なる完了点を持つ複数のイベントチェーンが存在する場合、関数は最長のチェーンのサイズのみ出力します。
構文
windowFunnel(window, [mode, [mode, ... ]])(timestamp, cond1, cond2, ..., condN)
引数
timestamp
— タイムスタンプを含むカラムの名前。サポートされているデータ型:Date、DateTimeおよびその他の符号なし整数型(タイムスタンプはUInt64
型をサポートしていますが、その値はInt64の最大値(2^63 - 1)を超えない必要があります)cond
— イベントチェーンを記述する条件またはデータ。UInt8。
パラメータ
window
— スライディングウィンドウの長さ、これは最初と最後の条件の間の時間間隔です。window
の単位はtimestamp
自体に依存し、異なります。式timestamp of cond1 <= timestamp of cond2 <= ... <= timestamp of condN <= timestamp of cond1 + window
を使用して決定されます。mode
— これはオプションの引数です。1つ以上のモードを設定できます。'strict_deduplication'
— イベントのシーケンスで同じ条件が成立している場合、そのような繰り返しイベントはさらに処理を中断します。注:複数の条件が同じイベントに対して成立した場合、予期しない動作が発生する可能性があります。'strict_order'
— 他のイベントの介入を許可しません。例:A->B->D->C
の場合、A->B->C
を見つけるのをD
で止め、最大イベントレベルは2です。'strict_increase'
— 厳密に増加するタイムスタンプのイベントにのみ条件を適用します。'strict_once'
— 条件に複数回一致しても、チェーン内で各イベントを一度だけカウントします。
返される値
スライディングタイムウィンドウ内のチェーンから連続してトリガーされた最大条件数。 選択内のすべてのチェーンが分析されます。
型:Integer
例
オンラインストアでユーザーが電話を2回選択して購入するのに十分な期間があるかどうかを判断します。
次のイベントチェーンを設定します:
- ユーザーがストアのアカウントにログインしました(
eventID = 1003
)。 - ユーザーが電話を検索しました(
eventID = 1007, product = 'phone'
)。 - ユーザーが注文をしました(
eventID = 1009
)。 - ユーザーが再度注文をしました(
eventID = 1010
)。
入力テーブル:
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-01-28 │ 1 │ 2019-01-29 10:00:00 │ 1003 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-01-31 │ 1 │ 2019-01-31 09:00:00 │ 1007 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-01-30 │ 1 │ 2019-01-30 08:00:00 │ 1009 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-02-01 │ 1 │ 2019-02-01 08:00:00 │ 1010 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
2019年1月〜2月の期間に、ユーザーuser_id
がどこまでチェーンを進むことができたかを調べます。
クエリ:
SELECT
level,
count() AS c
FROM
(
SELECT
user_id,
windowFunnel(6048000000000000)(timestamp, eventID = 1003, eventID = 1009, eventID = 1007, eventID = 1010) AS level
FROM trend
WHERE (event_date >= '2019-01-01') AND (event_date <= '2019-02-02')
GROUP BY user_id
)
GROUP BY level
ORDER BY level ASC;
結果:
┌─level─┬─c─┐
│ 4 │ 1 │
└───────┴───┘
retention
この関数は、イベントに対して特定の条件が満たされたかどうかを示すUInt8
型の1から32の引数からなる条件のセットを引数として受け取ります。
どんな条件でも引数として指定できます(WHEREのように)。
最初の条件を除いて、条件はペアで適用されます:2番目の結果が真になるのは、最初と2番目がともに真の場合、3番目の場合は最初と3番目がともに真の場合などです。
構文
retention(cond1, cond2, ..., cond32);
引数
cond
—UInt8
の結果(1または0)を返す式。
返される値
1または0の配列。
- 1 — イベントに対して条件が満たされた。
- 0 — イベントに対して条件が満たされなかった。
型:UInt8
。
例
サイトトラフィックを判断するためのretention
関数の計算例を考えてみましょう。
1. 例を示すためにテーブルを作成します。
CREATE TABLE retention_test(date Date, uid Int32) ENGINE = Memory;
INSERT INTO retention_test SELECT '2020-01-01', number FROM numbers(5);
INSERT INTO retention_test SELECT '2020-01-02', number FROM numbers(10);
INSERT INTO retention_test SELECT '2020-01-03', number FROM numbers(15);
入力テーブル:
クエリ:
SELECT * FROM retention_test
結果:
┌───────date─┬─uid─┐
│ 2020-01-01 │ 0 │
│ 2020-01-01 │ 1 │
│ 2020-01-01 │ 2 │
│ 2020-01-01 │ 3 │
│ 2020-01-01 │ 4 │
└────────────┴─────┘
┌───────date─┬─uid─┐
│ 2020-01-02 │ 0 │
│ 2020-01-02 │ 1 │
│ 2020-01-02 │ 2 │
│ 2020-01-02 │ 3 │
│ 2020-01-02 │ 4 │
│ 2020-01-02 │ 5 │
│ 2020-01-02 │ 6 │
│ 2020-01-02 │ 7 │
│ 2020-01-02 │ 8 │
│ 2020-01-02 │ 9 │
└────────────┴─────┘
┌───────date─┬─uid─┐
│ 2020-01-03 │ 0 │
│ 2020-01-03 │ 1 │
│ 2020-01-03 │ 2 │
│ 2020-01-03 │ 3 │
│ 2020-01-03 │ 4 │
│ 2020-01-03 │ 5 │
│ 2020-01-03 │ 6 │
│ 2020-01-03 │ 7 │
│ 2020-01-03 │ 8 │
│ 2020-01-03 │ 9 │
│ 2020-01-03 │ 10 │
│ 2020-01-03 │ 11 │
│ 2020-01-03 │ 12 │
│ 2020-01-03 │ 13 │
│ 2020-01-03 │ 14 │
└────────────┴─────┘
2. retention
関数を使用してuid
をユニークなユーザーIDでグループ化します。
クエリ:
SELECT
uid,
retention(date = '2020-01-01', date = '2020-01-02', date = '2020-01-03') AS r
FROM retention_test
WHERE date IN ('2020-01-01', '2020-01-02', '2020-01-03')
GROUP BY uid
ORDER BY uid ASC
結果:
┌─uid─┬─r───────┐
│ 0 │ [1,1,1] │
│ 1 │ [1,1,1] │
│ 2 │ [1,1,1] │
│ 3 │ [1,1,1] │
│ 4 │ [1,1,1] │
│ 5 │ [0,0,0] │
│ 6 │ [0,0,0] │
│ 7 │ [0,0,0] │
│ 8 │ [0,0,0] │
│ 9 │ [0,0,0] │
│ 10 │ [0,0,0] │
│ 11 │ [0,0,0] │
│ 12 │ [0,0,0] │
│ 13 │ [0,0,0] │
│ 14 │ [0,0,0] │
└─────┴─────────┘
3. 日ごとのサイト訪問数の合計を計算します。
クエリ:
SELECT
sum(r[1]) AS r1,
sum(r[2]) AS r2,
sum(r[3]) AS r3
FROM
(
SELECT
uid,
retention(date = '2020-01-01', date = '2020-01-02', date = '2020-01-03') AS r
FROM retention_test
WHERE date IN ('2020-01-01', '2020-01-02', '2020-01-03')
GROUP BY uid
)
結果:
┌─r1─┬─r2─┬─r3─┐
│ 5 │ 5 │ 5 │
└────┴────┴────┘
それぞれ:
r1
- 2020-01-01にサイトを訪れたユニークビジターの数(cond1
条件)。r2
- 特定の期間2020-01-01から2020-01-02の間にサイトを訪れたユニークビジターの数(cond1
およびcond2
条件)。r3
- 特定の期間2020-01-01と2020-01-03にサイトを訪れたユニークビジターの数(cond1
およびcond3
条件)。
uniqUpTo(N)(x)
引数の異なる値の数を指定された制限N
まで計算します。引数の異なる値の数がN
を超える場合、この関数はN
+1を返し、それ以外の場合は正確な値を計算します。
小さいN
(最大10まで)での使用を推奨します。N
の最大値は100です。
集計関数の状態のため、この関数は1 + N
* バイトの値の一つのサイズのメモリを使用します。
文字列を扱う場合、この関数は8バイトの非暗号化ハッシュを保存します。文字列の計算は近似的になります。
たとえば、あなたのウェブサイトでユーザーによって行われたすべての検索クエリを記録するテーブルがあったとします。テーブルの各行は単一の検索クエリを表し、ユーザーID、検索クエリ、クエリのタイムスタンプのカラムがあります。このデータを使用して、少なくとも5人のユニークユーザーが使用したキーワードのみを表示するレポートを生成するためにuniqUpTo
を使用できます。
SELECT SearchPhrase
FROM SearchLog
GROUP BY SearchPhrase
HAVING uniqUpTo(4)(UserID) >= 5
uniqUpTo(4)(UserID)
は各SearchPhrase
に対するユニークなUserID
値の数を計算しますが、最大4つのユニークな値だけを数えます。もしあるSearchPhrase
に対するユニークなUserID
値が4を超える場合、この関数は5(4 + 1)を返します。その後、HAVING
句はユニークなUserID
値が5未満のSearchPhrase
値をフィルタリングします。これにより、少なくとも5人のユニークユーザーが使用した検索キーワードのリストを取得することができます。
sumMapFiltered
この関数は、sumMapと同じ動作をしますが、フィルタリングに使用するキーの配列をパラメータとして受け取ることができます。これは、高いキーのカーディナリティを扱う際に特に役立ちます。
構文
sumMapFiltered(keys_to_keep)(keys, values)
パラメータ
返される値
- ソートされた順序のキーと、対応するキーに対して合計された値を持つ2つの配列のタプルを返します。
例
クエリ:
CREATE TABLE sum_map
(
`date` Date,
`timeslot` DateTime,
`statusMap` Nested(status UInt16, requests UInt64)
)
ENGINE = Log
INSERT INTO sum_map VALUES
('2000-01-01', '2000-01-01 00:00:00', [1, 2, 3], [10, 10, 10]),
('2000-01-01', '2000-01-01 00:00:00', [3, 4, 5], [10, 10, 10]),
('2000-01-01', '2000-01-01 00:01:00', [4, 5, 6], [10, 10, 10]),
('2000-01-01', '2000-01-01 00:01:00', [6, 7, 8], [10, 10, 10]);
SELECT sumMapFiltered([1, 4, 8])(statusMap.status, statusMap.requests) FROM sum_map;
結果:
┌─sumMapFiltered([1, 4, 8])(statusMap.status, statusMap.requests)─┐
1. │ ([1,4,8],[10,20,10]) │
└─────────────────────────────────────────────────────────────────┘
sumMapFilteredWithOverflow
この関数は、sumMapと同じ動作をしますが、フィルタリングに使用するキーの配列をパラメータとして受け取ることができます。これは、高いキーのカーディナリティを扱う際に特に役立ちます。sumMapFiltered関数とは異なり、オーバーフローを含む加算を行います - つまり、加算の結果のデータ型として引数のデータ型を返します。
構文
sumMapFilteredWithOverflow(keys_to_keep)(keys, values)
パラメータ
返される値
- ソートされた順序のキーと、対応するキーに対して合計された値を持つ2つの配列のタプルを返します。
例
この例では、テーブルsum_map
を作成し、データを挿入してからsumMapFilteredWithOverflow
とsumMapFiltered
をtoTypeName
関数と共に比較に使用します。作成したテーブルでrequests
はUInt8
型であった場合、sumMapFiltered
はオーバーフローを避けるために合計された値の型をUInt64
に昇格させたのに対し、sumMapFilteredWithOverflow
は型を引き続きUInt8
としており、これは結果を格納するには十分ではありません - つまり、オーバーフローが発生しています。
クエリ:
CREATE TABLE sum_map
(
`date` Date,
`timeslot` DateTime,
`statusMap` Nested(status UInt8, requests UInt8)
)
ENGINE = Log
INSERT INTO sum_map VALUES
('2000-01-01', '2000-01-01 00:00:00', [1, 2, 3], [10, 10, 10]),
('2000-01-01', '2000-01-01 00:00:00', [3, 4, 5], [10, 10, 10]),
('2000-01-01', '2000-01-01 00:01:00', [4, 5, 6], [10, 10, 10]),
('2000-01-01', '2000-01-01 00:01:00', [6, 7, 8], [10, 10, 10]);
SELECT sumMapFilteredWithOverflow([1, 4, 8])(statusMap.status, statusMap.requests) as summap_overflow, toTypeName(summap_overflow) FROM sum_map;
SELECT sumMapFiltered([1, 4, 8])(statusMap.status, statusMap.requests) as summap, toTypeName(summap) FROM sum_map;
結果:
┌─sum──────────────────┬─toTypeName(sum)───────────────────┐
1. │ ([1,4,8],[10,20,10]) │ Tuple(Array(UInt8), Array(UInt8)) │
└──────────────────────┴───────────────────────────────────┘
┌─summap───────────────┬─toTypeName(summap)─────────────────┐
1. │ ([1,4,8],[10,20,10]) │ Tuple(Array(UInt8), Array(UInt64)) │
└──────────────────────┴────────────────────────────────────┘
sequenceNextNode
一致したイベントチェーンの次のイベントの値を返します。
エクスペリメンタルな関数、SET allow_experimental_funnel_functions = 1
で有効にします。
構文
sequenceNextNode(direction, base)(timestamp, event_column, base_condition, event1, event2, event3, ...)
パラメータ
-
direction
— 移動の方向を指定します。- forward — 前進。
- backward — 後退。
-
base
— 基準点を設定するために使用します。- head — 基準点を最初のイベントに設定します。
- tail — 基準点を最後のイベントに設定します。
- first_match — 基準点を最初に一致した
event1
に設定します。 - last_match — 基準点を最後の一致した
event1
に設定します。
引数
timestamp
— タイムスタンプを含むカラムの名前。サポートされているデータ型:Date、DateTime およびその他の符号なし整数型。event_column
— 次に返されるイベントの値を含むカラムの名前。サポートされているデータ型:String と Nullable(String)。base_condition
— 基準点が満たすべき条件。event1
,event2
, ... — イベントチェーンを記述する条件。UInt8。
返される値
event_column[next_index]
— パターンが一致し、次の値が存在する場合。NULL
- パターンが一致しないか次の値が存在しない場合。
例
イベントがA->B->C->D->Eである場合、B->Cに続くイベントDを知りたいときに使用できます。
A->Bの後のイベントを検索するクエリステートメント:
CREATE TABLE test_flow (
dt DateTime,
id int,
page String)
ENGINE = MergeTree()
PARTITION BY toYYYYMMDD(dt)
ORDER BY id;
INSERT INTO test_flow VALUES (1, 1, 'A') (2, 1, 'B') (3, 1, 'C') (4, 1, 'D') (5, 1, 'E');
SELECT id, sequenceNextNode('forward', 'head')(dt, page, page = 'A', page = 'A', page = 'B') as next_flow FROM test_flow GROUP BY id;
結果:
┌─id─┬─next_flow─┐
│ 1 │ C │
└────┴───────────┘
forward
とhead
の動作
ALTER TABLE test_flow DELETE WHERE 1 = 1 settings mutations_sync = 1;
INSERT INTO test_flow VALUES (1, 1, 'Home') (2, 1, 'Gift') (3, 1, 'Exit');
INSERT INTO test_flow VALUES (1, 2, 'Home') (2, 2, 'Home') (3, 2, 'Gift') (4, 2, 'Basket');
INSERT INTO test_flow VALUES (1, 3, 'Gift') (2, 3, 'Home') (3, 3, 'Gift') (4, 3, 'Basket');
SELECT id, sequenceNextNode('forward', 'head')(dt, page, page = 'Home', page = 'Home', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home // 基準点、一致したHome
1970-01-01 09:00:02 1 Gift // Giftと一致
1970-01-01 09:00:03 1 Exit // 結果
1970-01-01 09:00:01 2 Home // 基準点、一致したHome
1970-01-01 09:00:02 2 Home // Giftと一致しない
1970-01-01 09:00:03 2 Gift
1970-01-01 09:00:04 2 Basket
1970-01-01 09:00:01 3 Gift // 基準点、Homeと一致しない
1970-01-01 09:00:02 3 Home
1970-01-01 09:00:03 3 Gift
1970-01-01 09:00:04 3 Basket
backward
とtail
の動作
SELECT id, sequenceNextNode('backward', 'tail')(dt, page, page = 'Basket', page = 'Basket', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home
1970-01-01 09:00:02 1 Gift
1970-01-01 09:00:03 1 Exit // 基準点、Basketと一致しない
1970-01-01 09:00:01 2 Home
1970-01-01 09:00:02 2 Home // 結果
1970-01-01 09:00:03 2 Gift // Giftと一致
1970-01-01 09:00:04 2 Basket // 基準点、Basketと一致
1970-01-01 09:00:01 3 Gift
1970-01-01 09:00:02 3 Home // 結果
1970-01-01 09:00:03 3 Gift // 基準点、Giftと一致
1970-01-01 09:00:04 3 Basket // 基準点、Basketと一致
forward
とfirst_match
の動作
SELECT id, sequenceNextNode('forward', 'first_match')(dt, page, page = 'Gift', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home
1970-01-01 09:00:02 1 Gift // 基準点
1970-01-01 09:00:03 1 Exit // 結果
1970-01-01 09:00:01 2 Home
1970-01-01 09:00:02 2 Home
1970-01-01 09:00:03 2 Gift // 基準点
1970-01-01 09:00:04 2 Basket // 結果
1970-01-01 09:00:01 3 Gift // 基準点
1970-01-01 09:00:02 3 Home // 結果
1970-01-01 09:00:03 3 Gift
1970-01-01 09:00:04 3 Basket
SELECT id, sequenceNextNode('forward', 'first_match')(dt, page, page = 'Gift', page = 'Gift', page = 'Home') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home
1970-01-01 09:00:02 1 Gift // 基準点
1970-01-01 09:00:03 1 Exit // Homeと一致しない
1970-01-01 09:00:01 2 Home
1970-01-01 09:00:02 2 Home
1970-01-01 09:00:03 2 Gift // 基準点
1970-01-01 09:00:04 2 Basket // Homeと一致しない
1970-01-01 09:00:01 3 Gift // 基準点
1970-01-01 09:00:02 3 Home // Homeと一致
1970-01-01 09:00:03 3 Gift // 結果
1970-01-01 09:00:04 3 Basket
backward
とlast_match
の動作
SELECT id, sequenceNextNode('backward', 'last_match')(dt, page, page = 'Gift', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home // 結果
1970-01-01 09:00:02 1 Gift // 基準点
1970-01-01 09:00:03 1 Exit
1970-01-01 09:00:01 2 Home
1970-01-01 09:00:02 2 Home // 結果
1970-01-01 09:00:03 2 Gift // 基準点
1970-01-01 09:00:04 2 Basket
1970-01-01 09:00:01 3 Gift
1970-01-01 09:00:02 3 Home // 結果
1970-01-01 09:00:03 3 Gift // 基準点
1970-01-01 09:00:04 3 Basket
SELECT id, sequenceNextNode('backward', 'last_match')(dt, page, page = 'Gift', page = 'Gift', page = 'Home') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home // Homeと一致、結果はnull
1970-01-01 09:00:02 1 Gift // 基準点
1970-01-01 09:00:03 1 Exit
1970-01-01 09:00:01 2 Home // 結果
1970-01-01 09:00:02 2 Home // Homeと一致
1970-01-01 09:00:03 2 Gift // 基準点
1970-01-01 09:00:04 2 Basket
1970-01-01 09:00:01 3 Gift // 結果
1970-01-01 09:00:02 3 Home // Homeと一致
1970-01-01 09:00:03 3 Gift // 基準点
1970-01-01 09:00:04 3 Basket
base_condition
の動作
CREATE TABLE test_flow_basecond
(
`dt` DateTime,
`id` int,
`page` String,
`ref` String
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(dt)
ORDER BY id;
INSERT INTO test_flow_basecond VALUES (1, 1, 'A', 'ref4') (2, 1, 'A', 'ref3') (3, 1, 'B', 'ref2') (4, 1, 'B', 'ref1');
SELECT id, sequenceNextNode('forward', 'head')(dt, page, ref = 'ref1', page = 'A') FROM test_flow_basecond GROUP BY id;
dt id page ref
1970-01-01 09:00:01 1 A ref4 // 基準点をヘッドにすることはできません。refカラムが'ref1'と一致しないため。
1970-01-01 09:00:02 1 A ref3
1970-01-01 09:00:03 1 B ref2
1970-01-01 09:00:04 1 B ref1
SELECT id, sequenceNextNode('backward', 'tail')(dt, page, ref = 'ref4', page = 'B') FROM test_flow_basecond GROUP BY id;
dt id page ref
1970-01-01 09:00:01 1 A ref4
1970-01-01 09:00:02 1 A ref3
1970-01-01 09:00:03 1 B ref2
1970-01-01 09:00:04 1 B ref1 // テールを基準点にすることはできません。refカラムが'ref4'と一致しないため。
SELECT id, sequenceNextNode('forward', 'first_match')(dt, page, ref = 'ref3', page = 'A') FROM test_flow_basecond GROUP BY id;
dt id page ref
1970-01-01 09:00:01 1 A ref4 // この行は基準点にはなりません。refカラムが'ref3'と一致しないため。
1970-01-01 09:00:02 1 A ref3 // 基準点
1970-01-01 09:00:03 1 B ref2 // 結果
1970-01-01 09:00:04 1 B ref1
SELECT id, sequenceNextNode('backward', 'last_match')(dt, page, ref = 'ref2', page = 'B') FROM test_flow_basecond GROUP BY id;
dt id page ref
1970-01-01 09:00:01 1 A ref4
1970-01-01 09:00:02 1 A ref3 // 結果
1970-01-01 09:00:03 1 B ref2 // 基準点
1970-01-01 09:00:04 1 B ref1 // この行は基準点にはなりません。refカラムが'ref2'と一致しないため。