mv-apply 运算符

对每个记录应用子查询,并返回所有子查询结果的并集。

例如,假设表 T 包含 dynamic 类型的列 Metric,其值为 real 数组成的数组。 下面的查询将在每个 Metric 值中找到两个最大值,并返回对应于这些值的记录。

T | mv-apply Metric to typeof(real) on 
(
   top 2 by Metric desc
)

mv-apply 运算符包括以下处理步骤:

  1. 使用 mv-expand 运算符将输入中的每条记录扩展为子表(顺序将保留)。
  2. 为每个子表应用子查询。
  3. 将零个或更多列添加到生成的子表。 这些列包含未扩展的源列的值,并在需要时重复。
  4. 返回结果的并集。

mv-apply 运算符获取以下输入:

  1. 一个或多个表达式,其计算结果为要扩展的动态数组。 每个扩展子表中的记录数是每个动态数组的最大长度。 如果指定了多个表达式,且相应数组的长度不同,则会添加 NULL 值。

  2. (可选)用于在扩展后分配表达式值的名称。 这些名称将成为子表中的列名。 如果未指定,则在表达式为列引用时使用列的原始名称。 否则,使用随机名称。

    注意

    建议使用默认列名。

  3. 扩展后,这些动态数组的元素的数据类型。 它们将成为子表中列的列类型。 如果未指定,则使用 dynamic

  4. (可选)要添加到子表中的列名,该列指定生成子表记录的数组中元素的从 0 开始的索引。

  5. (可选)要扩展的最大数组元素数。

可以将 mv-apply 运算符视为 mv-expand 运算符的通用化(事实上,如果子查询只包含投影,则后者可以通过前者来实现。)

语法

T|mv-apply [ItemIndex] ColumnsToExpand [RowLimit] on(SubQuery)

其中 ItemIndex 的语法如下:

with_itemindex=IndexColumnName

ColumnsToExpand 是以逗号分隔的列表,其中列出了一个或多个以下形式的元素:

[Name=] ArrayExpression [totypeof(Typename)]

RowLimit 只是:

limitRowLimit

SubQuery 具有与任何查询语句相同的语法。

详细了解语法约定

参数

客户 类型​​ 必需 说明
ItemIndex string 指示 long 类型的列的名称,该列在数组扩展阶段追加到输入,并指示扩展值的从 0 开始的数组索引。
Name string 名称,用于分配每个数组扩展表达式的数组扩展值。 如果未指定,则使用列名(如果可用)。 如果 ArrayExpression 不是简单的列名,则生成随机名称。
ArrayExpression dynamic 数组,其值将进行数组扩展。 如果表达式为输入中的列名,则会从输入中删除输入列,输出中将显示具有相同名称(如已指定,则为 ColumnName)的新列。
Typename string dynamic 数组 ArrayExpression 的各个元素采用的类型名称。 不符合此类型的元素将被替换为 NULL 值。 如果未指定,则默认情况下使用 dynamic
RowLimit int 基于每个输入记录生成的记录数限制。 如果未指定,则使用 2147483647。
SubQuery string 具有隐式表格源的表格查询表达式,应用于每个数组扩展子表。

注意

不同于 mv-expand 运算符,mv-apply 运算符不支持 bagexpand=array 扩展。 如果要扩展的表达式是属性包而不是数组,则可以使用内部 mv-expand 运算符(参阅下面的示例)。

示例

获取数组中最大的元素

let _data =
    range x from 1 to 8 step 1
    | summarize l=make_list(x) by xMod2 = x % 2;
_data
| mv-apply element=l to typeof(long) on 
    (
    top 1 by element
    )

输出

xMod2 l element
1 [1, 3, 5, 7] 7
0 [2, 4, 6, 8] 8

计算数组中最大的两个元素的总和

let _data =
    range x from 1 to 8 step 1
    | summarize l=make_list(x) by xMod2 = x % 2;
_data
| mv-apply l to typeof(long) on
    (
    top 2 by l
    | summarize SumOfTop2=sum(l)
    )

输出

xMod2 l SumOfTop2
1 [1,3,5,7] 12
0 [2,4,6,8] 14

选择数组中的元素

datatable (Val:int, Arr1:dynamic, Arr2:dynamic)
[ 1, dynamic(['A1', 'A2', 'A3']),       dynamic([10, 30, 7]), 
  7, dynamic(['B1', 'B2', 'B5']),       dynamic([15, 11, 50]),
  3, dynamic(['C1', 'C2', 'C3', 'C4']), dynamic([6, 40, 20, 8])
] 
| mv-apply NewArr1=Arr1, NewArr2=Arr2 to typeof(long) on (
 top 2 by NewArr2
 | summarize NewArr1=make_list(NewArr1), NewArr2=make_list(NewArr2)
)

输出

Val1 Arr1 Arr2 NewArr1 NewArr2
1 ["A1","A2","A3"] [10,30,7] ["A2',"A1"] [30,10]
7 ["B1","B2","B5"] [15,11,50] ["B5","B1"] [50,15]
3 ["C1","C2","C3","C4"] [6,40,20,8] ["C2","C3"] [40,20]

使用 with_itemindex 来处理数组的子集

let _data =
    range x from 1 to 10 step 1
    | summarize l=make_list(x) by xMod2 = x % 2;
_data
| mv-apply with_itemindex=index element=l to typeof(long) on 
    (
    // here you have 'index' column
    where index >= 3
    )
| project index, element

输出

index element
3 7
4 9
3 8
4 10

使用多个列联接 2 个数组的元素

datatable (Val: int, Arr1: dynamic, Arr2: dynamic)
[
    1, dynamic(['A1', 'A2', 'A3']), dynamic(['B1', 'B2', 'B3']), 
    5, dynamic(['C1', 'C2']), dynamic(['D1', 'D2'])
] 
| mv-apply Arr1, Arr2 on (
    extend Out = strcat(Arr1, "_", Arr2)
    | summarize Arr1 = make_list(Arr1), Arr2 = make_list(Arr2), Out= make_list(Out)
    )

输出

Val Arr1 Arr2 Out
1 ["A1","A2","A3"] ["B1","B2","B3"] ["A1_B1","A2_B2","A3_B3"]
5 ["C1","C2"] ["D1","D2"] ["C1_D1","C2_D2"]

将 mv-apply 应用于属性包

在下面的示例中,mv-apply 将与内部 mv-expand 结合使用以从属性包中删除不以“555”开头的值:

datatable(SourceNumber: string, TargetNumber: string, CharsCount: long)
[
    '555-555-1234', '555-555-1212', 46,
    '555-555-1212', '', int(null)
]
| extend values = pack_all()
| mv-apply removeProperties = values on 
    (
    mv-expand kind = array values
    | where values[1] !startswith "555"
    | summarize propsToRemove = make_set(values[0])
    )
| extend values = bag_remove_keys(values, propsToRemove)
| project-away propsToRemove

输出

SourceNumber TargetNumber CharsCount
555-555-1234 555-555-1212 46 {
"SourceNumber": "555-555-1234",
"TargetNumber": "555-555-1212"
}
555-555-1212     {
"SourceNumber": "555-555-1212"
}