练习 - 使用 let 语句引入变量
我们已使用气象数据集聚合和可视化数据。 在这里,你将了解如何使用 let
语句来引入变量和组织复杂查询。
let
语句可用于将复杂表达式分解为多个部分、定义查询正文外部的常量以便于阅读,或定义一次变量并在查询中多次使用它。 可以使用 let
语句创建组织有序的复杂查询。 可以使用多个 let
语句;每个语句必须后跟分号 (;
)。
let
语句可用于不同类型的情况。 在最简单的级别,可以定义稍后将在查询中引用的标量值,例如 int、字符串、日期/时间或任何其他值。 可以创建将用作查询的表格输入的表的表格筛选视图。 还可以使用 let
语句创建函数。
使用 let
语句定义标量
回顾一下,以前的查询已根据位置或最小损坏进行筛选。 让我们使用查询开头的 let
语句定义这些边界值。
以下查询使用两个 let
语句来定义稍后将用作查询中的输入参数的标量值。 第一个定义值是数字,第二个是字符串。 let
语句以分号结尾。
请注意以双正斜杠 (//
) 开头的查询中已注释掉的部分。 双正斜杠表示从注释的开头到行的末尾。 这些是运行查询时忽略的注释。
运行以下查询:
let MinDamage = 1; // int let EventLocation = "ARIZONA"; // string StormEvents | where State == EventLocation | where DamageCrops + DamageProperty >= MinDamage | summarize Damage=round(avg(DamageProperty + DamageCrops)) by EventType | sort by Damage
应获得如下图所示的结果:
尝试更改状态名称或最小损坏数并重新运行查询。 结果如何更改?
在 let
语句中使用 toscalar
将表格结果转换为标量值
接下来,让我们将最常见的事件类型计数视为时间函数。 首先,需要确定哪个是最常用的事件类型。 然后,你将在查询中使用此值。 使用 StormEvents 表通过计算每种类型中的事件数来查找排名靠前的 EventType。 使用 project
运算符仅返回 EventType 列。
在开始构造 let
语句之前,运行查询来找出此事件的实际含义。 这样,你便可以验证查询是否生成预期的结果。
StormEvents
| summarize count() by EventType
| top 1 by count_
| project EventType
应获得如下图所示的结果:
你会注意到,查询生成了包含一列和一行的表格结果。 但是,需要将此值转换为标量值,以用作主查询中的筛选器值。 首先,定义要引入为 MostFrequentEventType 的变量名称。 接下来,需要通过将整个查询放入 toscalar()
函数中来将表格结果转换为标量值。
以下 let
语句总结了上述步骤:
let MostFrequentEventType = toscalar(
StormEvents
| summarize count() by EventType
| top 1 by count_
| project EventType);
请注意,此语句本身不是有效的查询,因为有效的查询必须至少包含一个不是 let
语句的语句。 但是,可以在查询中使用此存储标量值。 回顾一下,你想要将最常用的事件时间计数视为时间函数。 你将根据 MostFrequentEventType 进行筛选,然后按特定时间箱汇总计数。
在本例中,我们来看看每月的结果。 你将使用 startofmonth()
函数,该函数返回表示给定日期值的月份开始的日期时间。 在此查询中,你会将 StartTime 列用作 startofmonth()
函数的输入。
最后,将结果呈现为柱形图,以获取按月份装箱的最常用事件类型的计数的直方图。
运行以下查询:
let MostFrequentEventType = toscalar( StormEvents | summarize count() by EventType | top 1 by count_ | project EventType); StormEvents | where EventType == MostFrequentEventType | summarize count() by startofmonth(StartTime) | render columnchart
应获得如下图所示的结果:
尝试更改查询以显示按月份装箱的最不常用事件类型的直方图并重新运行查询。
使用表格输出构造 let
语句
前面的示例创建了要用作查询中的输入参数的存储标量值。 但是,也可以使用 let
语句创建随后用作查询的输入的表格数据。
根据间接或直接导致死亡的事件筛选 StormEvents 表。 然后,使用
project
运算符返回列的子集。 此语句提供名为 KillerStorms 的表格输出。 将此let
语句用作查询的起始输入。let KillerStorms = StormEvents | where DeathsDirect + DeathsIndirect > 0 | project State, EventType, Deaths=DeathsDirect + DeathsIndirect;
然后,可以使用之前的单元中了解的一些聚合函数。 运行以下查询:
let KillerStorms = StormEvents | where DeathsDirect + DeathsIndirect > 0 | project State, EventType, Deaths=DeathsDirect + DeathsIndirect; KillerStorms | summarize DistinctKillerEventTypes=dcount(EventType), TotalDeaths=sum(Deaths) by State | sort by TotalDeaths
应获得如下图所示的结果:
查看结果。 DistinctKillerEventTypes 列中汇总的所有事件是否都称为“killer storms”?
使用 let
语句创建用户定义的函数
还可以使用 let
语句定义用户定义的函数,这些函数是可重用的子查询。 假设你想要弄清楚每个事件类型造成损坏的百分比。 你将创建用于计算百分比的用户定义的函数,稍后调用此函数并指定要用于计算百分比的列。
在 let
语句中,你将使用以下常规语法声明函数名称、参数和正文:
let function=(argument1:datatype, argument2:datatype) {functionbody};
具体而言,你将使用用户定义的函数来计算百分比。 首先,定义数据类型和输入参数。 对于此示例,你将使用以下参数:
参数名称 | 数据类型 | 说明 |
---|---|---|
部分 | real |
要计算其百分比的总事件部分。 |
total | real |
事件的总数。 |
你将使用 round()
函数将答案舍入为包含两位小数。
总而言之,let
语句描述的用户定义的函数为:
let Pcent = (portion:real, total:real){round(100 * portion / total, 2)};
在以下查询中使用此
let
语句:let Pcent = (portion: real, total: real) { round(100 * portion / total, 2) }; StormEvents | extend Damage = DamageCrops + DamageProperty | summarize TotalEvents = count(), TotalDamagingEvents = countif(Damage > 0) by EventType | project EventType, TotalDamagingEvents, TotalEvents, Percentage = Pcent(TotalDamagingEvents, TotalEvents) | sort by EventType asc
应获得如下图所示的结果:
请花点时间了解结果。 尝试修改查询,以按损坏类型显示百分比的细分并重新运行查询。
查看结果。 百分比的含义是什么? 请注意,查询调用我们在 let
语句中定义的 Pcent 函数。 此函数中使用的输入是 TotalDamagingEvents 和 TotalEvents,这意味着你要查找导致损坏的事件百分比。