今天学习一下在power query中使用Function.ScalarVector函数来优化我们调用的M函数公式。本例来自老外的博客文章:https://blog.crossjoin.co.uk/2018/11/16/function-scalarvector-optimise-power-query-m-functions/,我想试着按照原英文的步骤,来熟悉一下这个函数的使用。我们先看一下这个函数的基本解释:
这个函数能够使你将批量的函数请求和单行请求结合起来。下面我会跟着老外的例子来走一遍,熟悉理解下。下面是一个叫SingleValueUpper的函数,作用很简单,英文小写转大写:
(InputText as text) => Text.Upper(InputText)
现在创建一个名叫Product的表(table):
#table(
type table [Fruit=text],
{{"apples"},{"oranges"},{"pears"}}
)
平常一般做法就是Table.AddColumn(Product, "Fruit Upper", each SingleValueUpper([Fruit]))实现大小写转换。日常代码:
let
SingleValueUpper=(InputText as text) =>Text.Upper(InputText),
Product = #table(
type table [Fruit=text],
{{"apples"},{"oranges"},{"pears"}}
),
res=Table.AddColumn(Product, "Fruit Upper", each SingleValueUpper([Fruit]))
in
res
结果:
在上面的例子里,SingleValueUpper函数被调用了3次,每一行调用了一次。如果是这样调用网络服务的话,效率会非常的低。
现在来看看ListUpper函数:
(InputText as list) =>
List.Transform(
InputText,
each Text.Upper(_)
)
这个函数接受一个文本列表,并把里面的每个值转化为大写并返回一个列表结果。上面的例子我们可以通过ListUpper(Product[Fruit])就获得了水果的列表并完成转换了。 如果你是这样调用网络服务,会更高效。
Function.ScalarVector可以像这样通过引发函数开关来调用函数。来看下自定义一个ScalarVectorUpper函数:
Function.ScalarVector(
type function(Fruit as text) as text,
(InputTable) =>
let
BufferTable = Table.Buffer(InputTable),
InputList = BufferTable[Fruit],
CallFunction = ListUpper(InputList)
in
CallFunction
)
我们这里可以看到Function.ScalarVector的两个参数了:
第一个参数,匹配我们在调用的表的列的函数类型。
第二个参数,传递一个和函数类型(第一参数)相同列的表。文档里面说这个函数不能对表枚举超过一次。所以需要使用 Table.Buffer() 函数将表缓冲到内存里面,隔壁外部环境。
查询的代码如下;
let
ListUpper=(InputText as list) =>
List.Transform(
InputText,
each Text.Upper(_)
),
ScalarVectorUpper=Function.ScalarVector(
type function(Fruit as text) as text,
(InputTable) =>
let
BufferTable = Table.Buffer(InputTable),
InputList = BufferTable[Fruit],
CallFunction = ListUpper(InputList)
in
CallFunction
),
Product = #table(
type table [Fruit=text],
{{"apples"},{"oranges"},{"pears"}}
),
res=Table.AddColumn(Product, "Fruit Upper", each ScalarVectorUpper([Fruit]))
in
res
结果和前面常规的代码一样。不过这里数据太少,我没什么感觉,你可以自己试试。好了,我也熟悉一点了。