Azure Data Explorerのクエリを記述する

この記事では、Azure のデータ エクスプローラーのクエリ言語を使用し、最も一般的な演算子を含む基本的なクエリを実行する方法について説明します。 この言語のより高度な機能についても一部説明します。

前提条件

  • Microsoft アカウントまたは Azure Active Directory のユーザー ID。 Azure サブスクリプションは不要です。
  • クラスターとデータベースを作成します。

この記事では、2 つの方法のいずれかでクエリを実行できます。

クエリ言語の概要

Azure Data Explorer のクエリは、データを処理し、結果を返す、読み取り専用の要求です。 要求は、構文を読みやすく、作りやすく、自動化しやすくするように設計されたデータフロー モデルを利用してプレーンテキストで述べられます。 データベース、テーブル、列など、SQL に似た階層で整理されたスキーマ エンティティがクエリで使用されます。

クエリは一連のクエリ ステートメントで構成されます。ステートメントはセミコロン (;) で区切られ、少なくとも 1 つのステートメントを表形式にします。表形式のステートメントでは、生成されたデータが列と行からなる表のようなメッシュで整理されます。 クエリの表形式ステートメントからクエリの結果が生成されます。 2 つのステートメントは、セミコロンで区切る必要があります。

表形式ステートメントの構文では、ある表形式クエリ演算子から別の表形式クエリ演算子に表形式データが流れます。データ源 (データベースのテーブルやデータを生成する演算子など) から始まり、パイプ (|) 区切り記号でまとめられている一連のデータ変換演算子を通過します。

たとえば、次のクエリにはステートメントが 1 つありますが、それは表形式ステートメントです。 このステートメントは StormEvents という名前のテーブルの参照から始まっています (このテーブルをホストするデータベースはここでは接続情報の一部として暗に示されるだけです)。 そのテーブルのデータ (行) が StartTime 列の値でフィルター処理され、さらに State 列の値でフィルター処理されます。 "最後まで残った" 行の数がクエリにより返されます。

[クリックするとクエリが実行されます]

StormEvents
| where StartTime >= datetime(2007-11-01) and StartTime < datetime(2007-12-01)
| where State == "FLORIDA"
| count

このケースでは、結果は次のようになります。

Count
23

詳細については、「Query language reference」 (クエリ言語参照) を参照してください。

最も一般的な演算子

このセクションで取り上げる演算子は、Azure Data Explorerのクエリを理解するための基本となります。 記述するクエリの多くには、ここで説明する演算子がいくつか含まれます。

ヘルプ クラスターでクエリを実行するには、各クエリの上にある [クリックするとクエリが実行されます] を選択してください。

独自のクラスターでクエリを実行するには:

  1. 各クエリを Web ベース クエリ アプリケーションをコピーし、クエリを選択するか、クエリにカーソルを置きます。

  2. アプリケーションの上部にある [実行] を選択します。

count

count:テーブルの行数が返されます。

次のクエリでは、StormEvents テーブルの行数が返されます。

[クリックするとクエリが実行されます]

StormEvents | count

take

take:最大で指定のデータ行数まで返されます。

次のクエリでは、StormEvents テーブルから 5 行が返されます。 limit というキーワードは take のエイリアスです。

[クリックするとクエリが実行されます]

StormEvents | take 5

ヒント

ソース データが整理されていない限り、どのレコードが返されるかはわかりません。

project

project:列のサブセットが選択されます。

次のクエリでは、特定の列セットが返されます。

[クリックするとクエリが実行されます]

StormEvents
| take 5
| project StartTime, EndTime, State, EventType, DamageProperty, EpisodeNarrative

where

where:述語の条件を満たす行のサブセットにテーブルをフィルター処理します。

次のクエリでは、EventTypeState でデータが絞り込まれます。

[クリックするとクエリが実行されます]

StormEvents
| where EventType == 'Flood' and State == 'WASHINGTON'
| take 5
| project StartTime, EndTime, State, EventType, DamageProperty, EpisodeNarrative

sort

sort:入力テーブルの行を 1 つ以上の列の順序で並べ替えます。

次のクエリでは、DamageProperty の降順でデータが並べ替えられます。

[クリックするとクエリが実行されます]

StormEvents
| where EventType == 'Flood' and State == 'WASHINGTON'
| sort by DamageProperty desc
| take 5
| project StartTime, EndTime, State, EventType, DamageProperty, EpisodeNarrative

注意

演算の順序が重要です。 sort by の前に take 5 を置いてみてください。 違う結果が出ますか。

top

top:指定された列で並べ替えられた、先頭の N 個のレコードを返します。

次のクエリでは上と同じ結果が返されますが、演算子が 1 つ少なくなっています。

[クリックするとクエリが実行されます]

StormEvents
| where EventType == 'Flood' and State == 'WASHINGTON'
| top 5 by DamageProperty desc
| project StartTime, EndTime, State, EventType, DamageProperty, EpisodeNarrative

extend

extend:派生列が計算されます。

次のクエリでは、すべての行の値を計算することで、新しい列が作成されます。

[クリックするとクエリが実行されます]

StormEvents
| where EventType == 'Flood' and State == 'WASHINGTON'
| top 5 by DamageProperty desc
| extend Duration = EndTime - StartTime
| project StartTime, EndTime, Duration, State, EventType, DamageProperty, EpisodeNarrative

式には一般的な演算子 (+、-、*、/、%) をすべて含めることができます。また、各種の便利な関数を呼び出すことができます。

summarize

summarize:行のグループが集計されます。

次のクエリでは、State を基準にイベント数が返されます。

[クリックするとクエリが実行されます]

StormEvents
| summarize event_count = count() by State

summarize 演算子では、同じ値を持つ行が by 句でグループ化され、集計関数 (count など) が使用され、各グループが 1 つの行に組み合わされます。 そのため、このケースでは、州ごとに行が 1 つ与えられ、その州の行数用に列が 1 つ与えられます。

集計関数にはさまざまなものがあります。1 つの summarize 演算子でいくつかの集計関数を使用し、複数の列を計算できます。 たとえば、各州で発生した嵐の数とその一意の番号を取得し、top を使用して嵐の影響を最も受けた州を取得できます。

[クリックするとクエリが実行されます]

StormEvents
| summarize StormCount = count(), TypeOfStorms = dcount(EventType) by State
| top 5 by StormCount desc

summarize 演算の結果には以下が含まれます。

  • by で指定される各列

  • 計算された式ごとに 1 つの列

  • by 値の組み合わせごとに 1 つの行

render

render:結果がグラフィックで表現され、出力されます。

次のクエリでは、縦棒グラフが表示されます。

[クリックするとクエリが実行されます]

StormEvents
| summarize event_count=count(), mid = avg(BeginLat) by State
| sort by mid
| where event_count > 1800
| project State, event_count
| render columnchart

次のクエリでは、簡単な時間グラフが表示されます。

[クリックするとクエリが実行されます]

StormEvents
| summarize event_count=count() by bin(StartTime, 1d)
| render timechart

次のクエリでは、「StartTime % 1d」でイベントが数えられ、それが時間にまとめられ、時間グラフが表示されます。

[クリックするとクエリが実行されます]

StormEvents
| extend hour = floor(StartTime % 1d , 1h)
| summarize event_count=count() by hour
| sort by hour asc
| render timechart

次のクエリでは、連日の嵐が時間グラフで比較されます。

[クリックするとクエリが実行されます]

StormEvents
| extend hour= floor( StartTime % 1d , 1h)
| where State in ("GULF OF MEXICO","MAINE","VIRGINIA","WISCONSIN","NORTH DAKOTA","NEW JERSEY","OREGON")
| summarize event_count=count() by hour, State
| render timechart

注意

render 演算子は、エンジンに含まれるというより、むしろクライアント側の機能です。 使いやすいように言語に統合されています。 この Web アプリケーションはオプションとして棒グラフ、円柱グラフ、円グラフ、時間グラフ、折れ線グラフに対応しています。

スカラー演算子

このセクションでは、最も重要なスカラー演算子をいくつか取り上げます。

bin()

bin():値を切り捨てて、指定された bin サイズの倍数である整数にします。

次のクエリでは、1 日のバケット サイズで数が算出されます。

[クリックするとクエリが実行されます]

StormEvents
| where StartTime > datetime(2007-02-14) and StartTime < datetime(2007-02-21)
| summarize event_count = count() by bin(StartTime, 1d)

case()

case():述語の一覧が評価され、述語が満たされた最初の結果式か最後の else 式が返されます。 この演算子を使用し、データを分類またはグループ化できます。

次のクエリでは、新しい列 deaths_bucket が返され、死亡者が数でグループ化されます。

[クリックするとクエリが実行されます]

StormEvents
| summarize deaths = sum(DeathsDirect) by State
| extend deaths_bucket = case (
    deaths > 50, "large",
    deaths > 10, "medium",
    deaths > 0, "small",
    "N/A")
| sort by State asc

extract()

extract():テキスト文字列から正規表現との一致を取得します。

次のクエリでは、トレースから特定の属性値が抽出されます。

[クリックするとクエリが実行されます]

let MyData = datatable (Trace: string) ["A=1, B=2, Duration=123.45,...", "A=1, B=5, Duration=55.256, ..."];
MyData
| extend Duration = extract("Duration=([0-9.]+)", 1, Trace, typeof(real)) * time(1s)

このクエリでは let ステートメントが使用されますが、このステートメントにより名前 (この場合、MyData) が式にバインドされます。 let ステートメントが現れる残りのスコープについては (グローバル スコープまたは関数本体のスコープ)、この名前を使用してそのバインドされている値を参照できます。

parse_json()

parse_json():文字列が JSON 値として解釈され、値が dynamic として返されます。 複合 JSON オブジェクトの複数の要素を抽出する必要がある場合、extractjson() 関数の使用より優れています。

次のクエリでは、配列から JSON 要素が抽出されます。

[クリックするとクエリが実行されます]

let MyData = datatable (Trace: string)
['{"duration":[{"value":118.0,"valcount":5.0,"min":100.0,"max":150.0,"stdDev":0.0}]}'];
MyData
| extend NewCol = parse_json(Trace)
| project NewCol.duration[0].value, NewCol.duration[0].valcount, NewCol.duration[0].min, NewCol.duration[0].max, NewCol.duration[0].stdDev

次のクエリでは、JSON 要素が抽出されます。

[クリックするとクエリが実行されます]

let MyData = datatable (Trace: string) ['{"value":118.0,"valcount":5.0,"min":100.0,"max":150.0,"stdDev":0.0}'];
MyData
| extend NewCol = parse_json(Trace)
| project NewCol.value, NewCol.valcount, NewCol.min, NewCol.max, NewCol.stdDev

次のクエリでは、dynamic データ型の JSON 要素が抽出されます。

[クリックするとクエリが実行されます]

let MyData = datatable (Trace: dynamic)
[dynamic({"value":118.0,"counter":5.0,"min":100.0,"max":150.0,"stdDev":0.0})];
MyData
| project Trace.value, Trace.counter, Trace.min, Trace.max, Trace.stdDev

ago()

ago():現在の UTC 時刻から指定された期間を減算します。

次のクエリでは、過去 12 時間のデータが返されます。

[クリックするとクエリが実行されます]

//The first two lines generate sample data, and the last line uses
//the ago() operator to get records for last 12 hours.
print TimeStamp= range(now(-5d), now(), 1h), SomeCounter = range(1,121)
| mv-expand TimeStamp, SomeCounter
| where TimeStamp > ago(12h)

startofweek()

startofweek():日付を含む週の始まりが返されます。オフセットが指定されている場合、そのオフセットでシフトされます。

次のクエリでは、さまざまなオフセットで週の始まりが返されます。

[クリックするとクエリが実行されます]

range offset from -1 to 1 step 1
| project weekStart = startofweek(now(), offset),offset

このクエリでは range 演算子が使用されます。この演算子では、値の単一列テーブルが生成されます。 startofday()startofweek()startofyear())、startofmonth()endofday()endofweek()endofmonth()endofyear() も参照してください。

between()

between():両端を含む範囲内に入っている値が一致として出力されます。

次のクエリでは、指定のデータ範囲でデータが絞り込まれます。

[クリックするとクエリが実行されます]

StormEvents
| where StartTime between (datetime(2007-07-27) .. datetime(2007-07-30))
| count

次のクエリでも指定のデータ範囲でデータが絞り込まれますが、少しばかり変化を加え、開始日から 3 日間 (3d) と指定しています。

[クリックするとクエリが実行されます]

StormEvents
| where StartTime between (datetime(2007-07-27) .. 3d)
| count

テーブル演算子

Kusto にはさまざまなテーブル演算子があります。この記事の他のセクションでそのいくつかを取り上げます。 ここでは parse を取り上げます。

parse

parse:文字列式が評価され、その値が 1 つまたは複数の計算列に解析されます。 解析には、simple (既定)、regex、relaxed という 3 つの方法があります。

次のクエリでは、既定の simple 解析を利用し、トレースが解析され、関連値が抽出されます。 この式 (StringConstant と呼ばれる) は正規文字列値であり、一致は厳密です。拡張列が必須の型に一致する必要があります。

[クリックするとクエリが実行されます]

let MyTrace = datatable (EventTrace:string)
[
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=23, lockTime=02/17/2016 08:40:01Z, releaseTime=02/17/2016 08:40:01Z, previousLockTime=02/17/2016 08:39:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=15, lockTime=02/17/2016 08:40:00Z, releaseTime=02/17/2016 08:40:00Z, previousLockTime=02/17/2016 08:39:00Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=20, lockTime=02/17/2016 08:40:01Z, releaseTime=02/17/2016 08:40:01Z, previousLockTime=02/17/2016 08:39:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=22, lockTime=02/17/2016 08:41:01Z, releaseTime=02/17/2016 08:41:00Z, previousLockTime=02/17/2016 08:40:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=16, lockTime=02/17/2016 08:41:00Z, releaseTime=02/17/2016 08:41:00Z, previousLockTime=02/17/2016 08:40:00Z)'
];
MyTrace
| parse EventTrace with * "resourceName=" resourceName ", totalSlices=" totalSlices:long * "sliceNumber=" sliceNumber:long * "lockTime=" lockTime ", releaseTime=" releaseTime:date "," * "previousLockTime=" previouLockTime:date ")" *
| project resourceName ,totalSlices , sliceNumber , lockTime , releaseTime , previouLockTime

次のクエリでは、kind = regex を利用し、トレースが解析され、関連値が抽出されます。 StringConstant は正規表現にすることができます。

[クリックするとクエリが実行されます]

let MyTrace = datatable (EventTrace:string)
[
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=23, lockTime=02/17/2016 08:40:01Z, releaseTime=02/17/2016 08:40:01Z, previousLockTime=02/17/2016 08:39:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=15, lockTime=02/17/2016 08:40:00Z, releaseTime=02/17/2016 08:40:00Z, previousLockTime=02/17/2016 08:39:00Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=20, lockTime=02/17/2016 08:40:01Z, releaseTime=02/17/2016 08:40:01Z, previousLockTime=02/17/2016 08:39:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=22, lockTime=02/17/2016 08:41:01Z, releaseTime=02/17/2016 08:41:00Z, previousLockTime=02/17/2016 08:40:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=16, lockTime=02/17/2016 08:41:00Z, releaseTime=02/17/2016 08:41:00Z, previousLockTime=02/17/2016 08:40:00Z)'
];
MyTrace
| parse kind = regex EventTrace with "(.*?)[a-zA-Z]*=" resourceName @", totalSlices=\s*\d+\s*.*?sliceNumber=" sliceNumber:long  ".*?(previous)?lockTime=" lockTime ".*?releaseTime=" releaseTime ".*?previousLockTime=" previousLockTime:date "\\)"
| project resourceName , sliceNumber , lockTime , releaseTime , previousLockTime

次のクエリでは、kind = relaxed を利用し、トレースが解析され、関連値が抽出されます。 StringConstant は正規文字列値であり、一致は厳密ではありません。拡張列は必須の型に部分的に一致すれば一致と見なされます。

[クリックするとクエリが実行されます]

let MyTrace = datatable (EventTrace:string)
[
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=23, lockTime=02/17/2016 08:40:01Z, releaseTime=02/17/2016 08:40:01Z, previousLockTime=02/17/2016 08:39:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=15, lockTime=02/17/2016 08:40:00Z, releaseTime=02/17/2016 08:40:00Z, previousLockTime=02/17/2016 08:39:00Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=20, lockTime=02/17/2016 08:40:01Z, releaseTime=02/17/2016 08:40:01Z, previousLockTime=02/17/2016 08:39:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=22, lockTime=02/17/2016 08:41:01Z, releaseTime=02/17/2016 08:41:00Z, previousLockTime=02/17/2016 08:40:01Z)',
'Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=27, sliceNumber=16, lockTime=02/17/2016 08:41:00Z, releaseTime=02/17/2016 08:41:00Z, previousLockTime=02/17/2016 08:40:00Z)'
];
MyTrace
| parse kind=relaxed "Event: NotifySliceRelease (resourceName=PipelineScheduler, totalSlices=NULL, sliceNumber=23, lockTime=02/17/2016 08:40:01, releaseTime=NULL, previousLockTime=02/17/2016 08:39:01)" with * "resourceName=" resourceName ", totalSlices=" totalSlices:long * "sliceNumber=" sliceNumber:long * "lockTime=" lockTime ", releaseTime=" releaseTime:date "," * "previousLockTime=" previousLockTime:date ")" *
| project resourceName ,totalSlices , sliceNumber , lockTime , releaseTime , previousLockTime

時系列分析

make-series

make-series: summarize など、行のグループが集計されますが、by 値の組み合わせごとに (時) 系列ベクトルが生成されます。

次のクエリでは、1 日あたりの嵐の数に対して一連の時系列が返されます。 このクエリでは、州ごとに 3 か月という期間が考慮されます。足りない値域は定数 0 で埋められます。

[クリックするとクエリが実行されます]

StormEvents
| make-series n=count() default=0 on StartTime in range(datetime(2007-01-01), datetime(2007-03-31), 1d) by State

一連の (時) 系列を作成したら、系列関数を適用し、異常な形状や季節のパターンなどを検出できます。

次のクエリでは、特定の日に嵐が最も多く発生した上位 3 州が抽出されます。

[クリックするとクエリが実行されます]

StormEvents
| make-series n=count() default=0 on StartTime in range(datetime(2007-01-01), datetime(2007-03-31), 1d) by State
| extend series_stats(n)
| top 3 by series_stats_n_max desc
| render timechart

詳細については、系列関数の完全一覧をご覧ください。

高度な集計

この記事の前半では、countsummarize など、基本的な集計を取り上げました。 このセクションでは、より高度なオプションを紹介します。

top-nested

top-nested:上位の結果が階層型で生成されます。各レベルは前のレベル値に基づくドリルダウンになります。

この演算子は、ダッシュボード視覚化シナリオや、質問に対して答える必要がある場合に便利です。たとえば、"(何らかの集計を使用して) K1 の上位 N の値を見つけて、その値のそれぞれに対して (別の集計を使用して) K2 の上位 M の値を見つけて、..." のような質問です。

次のクエリでは、最上位を State、その次を Sources として階層型テーブルが返されます。

[クリックするとクエリが実行されます]

StormEvents
| top-nested 2 of State by sum(BeginLat),
top-nested 3 of Source by sum(BeginLat),
top-nested 1 of EndLocation by sum(BeginLat)

pivot() プラグイン

pivot() plugin:入力テーブルのある列の一意の値を出力テーブルの複数の列に変えるという方法でテーブルを回転させます。 この演算子では、最終的な出力の残りの列値で集計が必要になる箇所で集計が実行されます。

次のクエリではフィルターが適用され、行が回転して列になります。

[クリックするとクエリが実行されます]

StormEvents
| project State, EventType
| where State startswith "AL"
| where EventType has "Wind"
| evaluate pivot(State)

dcount()

dcount():グループ内のある式の個別値の数が見積もられ、返されます。 すべての値を数える際に count() を使用します。

次のクエリでは、個別の SourceState を基準に数えられます。

[クリックするとクエリが実行されます]

StormEvents
| summarize Sources = dcount(Source) by State

dcountif()

dcountif():評価の結果、述語が真であるとされた行の式の個別値の数が見積もられ、返されます。

次のクエリでは、DamageProperty < 5000 となっている Source の個別値が数えられます。

[クリックするとクエリが実行されます]

StormEvents
| take 100
| summarize Sources = dcountif(Source, DamageProperty < 5000) by State

dcount_hll()

dcount_hll():(hll または hll_merge によって生成される) HyperLogLog 結果から dcount が計算されます。

次のクエリでは、HLL アルゴリズムを使用してカウントが生成されます。

[クリックするとクエリが実行されます]

StormEvents
| summarize hllRes = hll(DamageProperty) by bin(StartTime,10m)
| summarize hllMerged = hll_merge(hllRes)
| project dcount_hll(hllMerged)

arg_max()

arg_max():グループ内で式を最大化する行を見つけ、別の式の値を返します (* の場合、式全体が返されます)。

次のクエリでは、各州で最後に洪水が報告された時刻が返されます。

[クリックするとクエリが実行されます]

StormEvents
| where EventType == "Flood"
| summarize arg_max(StartTime, *) by State
| project State, StartTime, EndTime, EventType

makeset()

makeset():グループ内である式により受け取られる個別値セットを dynamic (JSON) 配列で返します。

次のクエリでは、各州より洪水が報告された時刻がすべて返され、個別値セットから配列が作成されます。

[クリックするとクエリが実行されます]

StormEvents
| where EventType == "Flood"
| summarize FloodReports = makeset(StartTime) by State
| project State, FloodReports

mv-expand

mv-expand:コレクション内の各値に別個の行が与えられるように、動的に型指定された列から複数値のコレクションが展開されます。 展開された行内のその他の列はすべて複製されます。 makelist の反対になります。

次のクエリでは、1 つのセットを作成し、それを利用して mv-expand 機能を実行するという方法でサンプル データが生成されます。

[クリックするとクエリが実行されます]

let FloodDataSet = StormEvents
| where EventType == "Flood"
| summarize FloodReports = makeset(StartTime) by State
| project State, FloodReports;
FloodDataSet
| mv-expand FloodReports

percentiles()

percentiles():式により定義される人口について、指定の最も近いランクのパーセンタイルに対する見積もりを返します。 精度は、パーセンタイル リージョンの人口密度によって異なります。 summarize 内の集計というコンテキストでのみ使用できます。

次のクエリでは、嵐の継続時間に対してパーセンタイルが計算されます。

[クリックするとクエリが実行されます]

StormEvents
| extend duration = EndTime - StartTime
| where duration > 0s
| where duration < 3h
| summarize percentiles(duration, 5, 20, 50, 80, 95)

次のクエリでは、嵐の継続時間に対するパーセンタイルが州別に計算され、5 分 (5m) という値域でデータが正規化されます。

[クリックするとクエリが実行されます]

StormEvents
| extend duration = EndTime - StartTime
| where duration > 0s
| where duration < 3h
| summarize event_count = count() by bin(duration, 5m), State
| summarize percentiles(duration, 5, 20, 50, 80, 95) by State

データセットを超える

このセクションでは、より複雑なクエリを作成したり、複数のテーブル間でデータを結合したり、すべてのデータベースやクラスターにわたってクエリを実行したりできます。

let

let:モジュール性と再利用性が向上します。 let ステートメントでは、複雑になる可能性がある式を複数の部分に分割し、それぞれに名前を関連付け、そのような部品を組み立てることができます。 let ステートメントは、ユーザー定義の関数やビュー (結果が新しいテーブルのように見えるテーブルの式) を作成する目的にも使用できます。 let ステートメントでバインドされる式は、スカラー型、表型、またはユーザー定義関数 (ラムダ) になります。

次の例では表型の変数が作成され、それが後続の式で使用されます。

[クリックするとクエリが実行されます]

let LightningStorms =
StormEvents
| where EventType == "Lightning";
let AvalancheStorms =
StormEvents
| where EventType == "Avalanche";
LightningStorms
| join (AvalancheStorms) on State
| distinct State

join

join:各テーブルの指定の列で値を照合することで、2 つのテーブルの行を結合し、新しいテーブルを形成します。 Kusto では、fullouterinnerinneruniqueleftantileftantisemileftouterleftsemirightantirightantisemirightouterrightsemi というすべての結合型に対応しています。

次の例では、内部結合を使用して 2 つのテーブルが結合されます。

[クリックするとクエリが実行されます]

let X = datatable(Key:string, Value1:long)
[
    'a',1,
    'b',2,
    'b',3,
    'c',4
];
let Y = datatable(Key:string, Value2:long)
[
    'b',10,
    'c',20,
    'c',30,
    'd',40
];
X
| join kind=inner Y on Key

ヒント

結合の前に入力テーブルの行と列の数を減らすには、whereproject を使用します。 一方のテーブルがもう一方よりも常に小さい場合は、それを結合の左側 (パイプされる側) として使います。 一致した場合に結合する列は、同じ名前を持つ必要があります。 いずれかのテーブルで列の名前を変更する必要がある場合は、project 演算子を使用します。

serialize

serialize:row_number() のようなシリアル化されたデータを必要とする関数を使用できるように、行セットがシリアル化されます。

データがシリアル化されているため、次のクエリは成功します。

[クリックするとクエリが実行されます]

StormEvents
| summarize count() by State
| serialize
| extend row_number = row_number()

行セットは、それが sorttoprange 演算子の結果であり、任意で後ろに projectproject-awayextendwhereparsemv-expandtake 演算子が続く場合も、シリアル化されていると見なされます。

[クリックするとクエリが実行されます]

StormEvents
| summarize count() by State
| sort by State asc
| extend row_number = row_number()

複数のデータベースに対するクエリと複数のクラスターに対するクエリ

複数のデータベースに対するクエリと複数のクラスターに対するクエリ:database("MyDatabase").MyTable として参照すれば、同じクラスター上のデータベースにクエリを実行できます。 cluster("MyCluster").database("MyDatabase").MyTable として参照すれば、リモート クラスター上のデータベースにクエリを実行できます。

次のクエリはあるクラスターから呼び出され、MyCluster クラスターのデータを問い合わせます。 このクエリを実行するには、独自のクラスター名とデータベース名を使用します。

cluster("MyCluster").database("Wiki").PageViews
| where Views < 2000
| take 1000;

ユーザー分析

このセクションには、Kusto ではいかに簡単にユーザーの行動を分析できるかということを示す要素とクエリが含まれています。

activity_counts_metrics プラグイン

activity_counts_metrics プラグイン:有用なアクティビティ指標が計算されます (合計カウント値、個別カウント値、新しい値の個別カウント、集計個別カウント)。 指標は時間枠ごとに計算され、比較され、前のすべての時間枠と共に集計されます。

次のクエリでは、毎日のアクティビティ カウントを計算することでユーザー導入が分析されます。

[クリックするとクエリが実行されます]

let start=datetime(2017-08-01);
let end=datetime(2017-08-04);
let window=1d;
let T = datatable(UserId:string, Timestamp:datetime)
[
'A', datetime(2017-08-01),
'D', datetime(2017-08-01),
'J', datetime(2017-08-01),
'B', datetime(2017-08-01),
'C', datetime(2017-08-02),
'T', datetime(2017-08-02),
'J', datetime(2017-08-02),
'H', datetime(2017-08-03),
'T', datetime(2017-08-03),
'T', datetime(2017-08-03),
'J', datetime(2017-08-03),
'B', datetime(2017-08-03),
'S', datetime(2017-08-03),
'S', datetime(2017-08-04),
];
T
| evaluate activity_counts_metrics(UserId, Timestamp, start, end,
window)

activity_engagement プラグイン

activity_engagement プラグイン:変化するタイムライン ウィンドウを対象に、ID 列に基づいてアクティビティ エンゲージメント率が計算されます。 activity_engagement プラグインは、DAU、WAU、MAU (毎日、毎週、毎月のアクティブ ユーザー) の計算に利用できます。

次のクエリでは、7 日間の移動ウィンドウを対象に、あるアプリケーションを毎日使用するユーザーの合計とそのアプリケーションを週単位で使用するユーザーの合計の比率が返されます。

[クリックするとクエリが実行されます]

// Generate random data of user activities
let _start = datetime(2017-01-01);
let _end = datetime(2017-01-31);
range _day from _start to _end step 1d
| extend d = tolong((_day - _start)/1d)
| extend r = rand()+1
| extend _users=range(tolong(d*50*r), tolong(d*50*r+100*r-1), 1)
| mv-expand id=_users to typeof(long) limit 1000000
// Calculate DAU/WAU ratio
| evaluate activity_engagement(['id'], _day, _start, _end, 1d, 7d)
| project _day, Dau_Wau=activity_ratio*100
| render timechart

ヒント

DAU/MAU を計算するとき、エンド データと移動ウィンドウ期間 (OuterActivityWindow) を変更します。

activity_metrics プラグイン

activity_metrics プラグイン:現在の期間と前の期間に基づいて、有用なアクティビティ指標 (個別カウント値、新しい値の個別カウント、保有率、解約率) を計算し、比較します。

次のクエリでは、指定のデータセットに対して解約率と保有率が計算されます。

[クリックするとクエリが実行されます]

// Generate random data of user activities
let _start = datetime(2017-01-02);
let _end = datetime(2017-05-31);
range _day from _start to _end step 1d
| extend d = tolong((_day - _start)/1d)
| extend r = rand()+1
| extend _users=range(tolong(d*50*r), tolong(d*50*r+200*r-1), 1)
| mv-expand id=_users to typeof(long) limit 1000000
| where _day > datetime(2017-01-02)
| project _day, id
// Calculate weekly retention rate
| evaluate activity_metrics(['id'], _day, _start, _end, 7d)
| project _day, retention_rate*100, churn_rate*100
| render timechart

new_activity_metrics プラグイン

new_activity_metrics プラグイン:新しいユーザーの集合に対して有用なアクティビティ指標 (個別カウント値、新しい値の個別カウント、保有率、解約率) を計算し、比較します。 このプラグインの概念は activity_metrics plugin に似ていますが、新しいユーザーに焦点が置かれます。

次のクエリでは、新しいユーザーの集合 (最初の週に現れたユーザー) を対象に、週単位の保有率と解約率が計算されます。

[クリックするとクエリが実行されます]

// Generate random data of user activities
let _start = datetime(2017-05-01);
let _end = datetime(2017-05-31);
range Day from _start to _end step 1d
| extend d = tolong((Day - _start)/1d)
| extend r = rand()+1
| extend _users=range(tolong(d*50*r), tolong(d*50*r+200*r-1), 1)
| mv-expand id=_users to typeof(long) limit 1000000
// Take only the first week cohort (last parameter)
| evaluate new_activity_metrics(['id'], Day, _start, _end, 7d, _start)
| project from_Day, to_Day, retention_rate, churn_rate

session_count プラグイン

session_count プラグイン:あるタイムラインを対象に ID 列に基づいてセッションの数が計算されます。

次のクエリでは、セッション数が返されます。 セッションは、あるユーザー ID が 100 個の時間帯の時間枠の中で少なくとも 1 回現れる場合 (そのとき、セッションの遡りウィンドウは 41 個の時間帯) にアクティブと見なされます。

[クリックするとクエリが実行されます]

let _data = range Timeline from 1 to 9999 step 1
| extend __key = 1
| join kind=inner (range Id from 1 to 50 step 1 | extend __key=1) on __key
| where Timeline % Id == 0
| project Timeline, Id;
// End of data definition
_data
| evaluate session_count(Id, Timeline, 1, 10000, 100, 41)
| render linechart

funnel_sequence プラグイン

funnel_sequence プラグイン:ある一連の状態を経たユーザーの個別カウントが計算されます。その連続につながった、あるいはその連続が後に続いた前の状態と次の状態の分布が表示されます。

次のクエリでは、2007 年にすべての竜巻の前後で発生したイベントが表示されます。

[クリックするとクエリが実行されます]

// Looking on StormEvents statistics:
// Q1: What happens before Tornado event?
// Q2: What happens after Tornado event?
StormEvents
| evaluate funnel_sequence(EpisodeId, StartTime, datetime(2007-01-01), datetime(2008-01-01), 1d,365d, EventType, dynamic(['Tornado']))

funnel_sequence_completion プラグイン

funnel_sequence_completion プラグイン:異なる期間内で完了したシーケンス ステップのフィルターが計算されます。

次のクエリでは、1 時間、4 時間、1 日 ([1h, 4h, 1d]) という "全体" 時間を対象に、Hail -> Tornado -> Thunderstorm -> Wind という順序の完了したフィルターが確認されます。

[クリックするとクエリが実行されます]

let _start = datetime(2007-01-01);
let _end = datetime(2008-01-01);
let _windowSize = 365d;
let _sequence = dynamic(['Hail', 'Tornado', 'Thunderstorm', 'Wind']);
let _periods = dynamic([1h, 4h, 1d]);
StormEvents
| evaluate funnel_sequence_completion(EpisodeId, StartTime, _start, _end, _windowSize, EventType, _sequence, _periods)

関数

このセクションでは、関数を扱います。サーバー上に保管される再利用可能なクエリです。 関数はクエリや他の関数で呼び出すことができます (再帰関数はサポートされていません)。

注意

ヘルプ センターで関数を作成することはできません。読み取り専用です。 この部分には独自のテスト クラスターを使用します。

次の例では、引数として州名 (MyState) を受け取る関数が作成されます。

.create function with (folder="Demo")
MyFunction (MyState: string)
{
StormEvents
| where State =~ MyState
}

次の例では、テキサス州のデータを取得する関数が呼び出されます。

MyFunction ("Texas")
| summarize count()

次の例では、最初の手順で作成された関数が削除されます。

.drop function MyFunction

次のステップ

Kusto クエリ言語リファレンス