Microsoft Power Query 提供了强大的“获取数据”体验,其中包含许多功能。Power Query 的一项核心功能是筛选和组合,即“混搭”来自一个或多个受支持数据源的丰富集合中的数据。任何此类数据混搭均使用 Power Query 公式语言(非正式称为“M”)表示。Power Query 将 M 文档嵌入 Excel 和 Power BI 工作簿中,以实现可重复的数据混搭。
本文档提供了 M 的规范。经过旨在建立对语言的初步直觉和熟悉的简要介绍后,文档准确地分几个渐进步骤涵盖了该语言:
对于计算机语言理论家:本文档中指定的公式语言是一种主要是纯粹的、高阶的、动态类型的、部分惰性的函数式语言。
M 中的核心结构是表达式。一个表达式可以被评估(计算),产生一个单一的值。
尽管许多值可以按字面写成表达式,但值不是表达式。例如,表达式的1
计算结果为1;表达式的1+1
计算结果为2。这种区别很微妙,但很重要。表达式是求值的方法;值是评估的结果。
以下示例说明了 M 中可用的不同类型的值。按照惯例,值使用字面形式写入,它们将出现在计算结果为该值的表达式中。(请注意,//
表示继续到行尾的注释的开始。)
{
和}
表示列表的开头和结尾。
复制
{123, true, "A"} // list containing a number, a logical, and // a text {1, 2, 3} // list of three numbers A
”,“ B
”和“ C
”,其中有值1
,2
和3
。
复制
[ A = 1, B = 2, C = 3 ]=>
,然后是定义函数的表达式。该表达式通常是指参数(按名称)。
复制
(x, y) => (x + y) / 2`M语言的评估模型是仿照电子表格中常见的评估模型建模的,其中计算顺序可以根据单元格中公式之间的依赖关系确定。
如果您在 Excel 等电子表格中编写了公式,您可能会发现左侧的公式在计算时会产生右侧的值:
在 M 中,表达式的部分可以通过名称引用表达式的其他部分,并且评估过程将自动确定引用表达式的计算顺序。
我们可以使用一个记录来生成一个表达式,它相当于上面的电子表格示例。在初始化一个字段的值时,我们可以通过字段名来引用记录内的其他字段,如下:
复制
[
A1 = A2 * 2,
A2 = A3 + 1,
A3 = 1
]
上面的表达式等效于以下表达式(因为两者的计算结果相等):
复制
[
A1 = 4,
A2 = 2,
A3 = 1
]
记录可以包含在或嵌套在其他记录中。我们可以使用查找运算符( []
) 按名称访问记录的字段。例如,以下记录有一个名为Sales
包含记录的字段,以及一个名为Total
访问记录的FirstHalf
和SecondHalf
字段的字段Sales
:
复制
[
Sales = [ FirstHalf = 1000, SecondHalf = 1100 ],
Total = Sales[FirstHalf] + Sales[SecondHalf]
]
上面的表达式在计算时等效于以下内容:\
复制
[
Sales = [ FirstHalf = 1000, SecondHalf = 1100 ],
Total = 2100
]
记录也可以包含在列表中。我们可以使用位置索引运算符( {}
) 通过其数字索引访问列表中的项目。列表中的值使用从列表开头开始的从零开始的索引来引用。例如,索引0
和1
用于引用以下列表中的第一项和第二项:
复制
[
Sales =
{
[
Year = 2007,
FirstHalf = 1000,
SecondHalf = 1100,
Total = FirstHalf + SecondHalf // 2100
],
[
Year = 2008,
FirstHalf = 1200,
SecondHalf = 1300,
Total = FirstHalf + SecondHalf // 2500
]
},
TotalSales = Sales{0}[Total] + Sales{1}[Total] // 4600
]
列表和记录成员表达式(以及下面进一步介绍的 let 表达式)使用惰性求值进行求值,这意味着它们仅在需要时进行求值。所有其他表达式都使用Eager Evaluation 求值,这意味着在求值过程中遇到它们时会立即求值。考虑这一点的一个好方法是记住,评估列表或记录表达式将返回一个列表或记录值,该值本身记住在请求时(通过查找或索引运算符)需要如何计算其列表项或记录字段。
在 M 中,函数是从一组输入值到单个输出值的映射。编写函数时,首先命名所需的一组输入值(函数的参数),然后提供一个表达式,该表达式将使用这些输入值(函数的主体)来计算函数的结果(函数的主体)。=>
) 象征。例如:
复制
(x) => x + 1 // function that adds one to a value
(x, y) => x + y // function that adds two values
函数是一个值,就像数字或文本值一样。下面的示例显示了一个函数,它是一个 Add 字段的值,然后从其他几个字段调用或执行该函数。调用函数时,会指定一组值,这些值在逻辑上会替换函数体表达式中所需的一组输入值。
复制
[
Add = (x, y) => x + y,
OnePlusOne = Add(1, 1), // 2
OnePlusTwo = Add(1, 2) // 3
]
M 包括一组通用定义,可从称为标准库或简称为库的表达式中使用。这些定义由一组命名值组成。库提供的值的名称可在表达式中使用,而无需由表达式明确定义。例如:
复制
Number.E // Euler's number e (2.7182...)
Text.PositionOf("Hello", "ll") // 2
M 包括一组可在表达式中使用的运算符。运算符应用于操作数以形成符号表达式。例如,在表达式中1 + 2
,数字1
和2
是操作数,运算符是加法运算符 ( +
)。
运算符的含义可以根据其操作数是什么类型的值而有所不同。例如,加号运算符可用于数字以外的其他类型的值:
复制
1 + 2 // numeric addition: 3
#time(12,23,0) + #duration(0,0,2,0)
// time arithmetic: #time(12,25,0)
具有操作数相关含义的运算符的另一个示例是组合运算符 ( &
):
复制
"A" & "BC" // text concatenation: "ABC"
{1} & {2, 3} // list concatenation: {1, 2, 3}
[ a = 1 ] & [ b = 2 ] // record merge: [ a = 1, b = 2 ]
请注意,运算符可能不支持所有值的组合。例如:
复制
1 + "2" // error: adding number and text is not supported
计算时遇到未定义运算符条件的表达式计算为错误。稍后会详细介绍 M 中的错误。
元数据是关于与值关联的值的信息。元数据表示为记录值,称为元数据记录。元数据记录的字段可用于存储值的元数据。
每个值都有一个元数据记录。如果未指定元数据记录的值,则元数据记录为空(没有字段)。
元数据记录提供了一种以不显眼的方式将附加信息与任何类型的值相关联的方法。将元数据记录与值相关联不会改变该值或其行为。
元数据记录值使用语法y
与现有值相关联。例如,以下将元数据记录与文本值和字段相关联:xx meta yRatingTags"Mozart"
复制
"Mozart" meta [ Rating = 5, Tags = {"Classical"} ]
对于已经携带非空元数据记录的值,应用元数据的结果是计算现有和新元数据记录的记录合并。例如,以下两个表达式彼此等效,并且与前面的表达式等效:
复制
("Mozart" meta [ Rating = 5 ]) meta [ Tags = {"Classical"} ]
"Mozart" meta ([ Rating = 5 ] & [ Tags = {"Classical"} ])
可以使用Value.Metadata函数访问给定值的元数据记录。在下面的示例中,ComposerRating
字段中的表达式访问字段中值的元数据记录Composer
,然后访问Rating
元数据记录的字段。
复制
[
Composer = "Mozart" meta [ Rating = 5, Tags = {"Classical"} ],
ComposerRating = Value.Metadata(Composer)[Rating] // 5
]
迄今为止显示的许多示例都在表达式的结果中包含了表达式的所有文字值。该设表达式允许的一组值被计算,分配的名称,然后在随后的一个随后的表达式中使用的。例如,在我们的销售数据示例中,我们可以执行以下操作:
复制
let
Sales2007 =
[
Year = 2007,
FirstHalf = 1000,
SecondHalf = 1100,
Total = FirstHalf + SecondHalf // 2100
],
Sales2008 =
[
Year = 2008,
FirstHalf = 1200,
SecondHalf = 1300,
Total = FirstHalf + SecondHalf // 2500
]
in Sales2007[Total] + Sales2008[Total] // 4600
上面表达式的结果是一个数值 ( 4600
),它是根据绑定到名称Sales2007
和的值计算得出的Sales2008
。
所述if
基于逻辑条件两个表达式之间的表达进行选择。例如:
复制
if 2 > 1 then
2 + 2
else
1 + 1
2 + 2
如果逻辑表达式 ( 2 > 1
) 为真,则选择第一个表达式 ( ),如果逻辑表达式1 + 1
为假,则选择第二个表达式 ( )。选定的表达式(在本例中2 + 2
)被评估并成为if
表达式 ( 4
)的结果。
的错误是计算表达式的过程中不能产生的值的指示。
错误由遇到错误条件的运算符和函数或通过使用错误表达式引发。使用 try 表达式处理错误。出现错误时,会指定一个值,该值可用于指示发生错误的原因。
复制
let Sales =
[
Revenue = 2000,
Units = 1000,
UnitPrice = if Units = 0 then error "No Units"
else Revenue / Units
],
UnitPrice = try Number.ToText(Sales[UnitPrice])
in "Unit Price: " &
(if UnitPrice[HasError] then UnitPrice[Error][Message]
else UnitPrice[Value])
上面的示例访问Sales[UnitPrice]
字段并格式化产生结果的值:
复制
"Unit Price: 2"
如果该Units
字段为零,则该UnitPrice
字段将引发一个错误,该错误将由try
. 结果值将是:
复制
"No Units"
甲try
表达适当的值和错误转换成记录值,指示尝试表达是否处理和错误,或没有,并且或者适当的值或错误记录它处理错误时萃取。例如,考虑以下引发错误然后立即处理的表达式:
复制
try error "negative unit count"
该表达式评估为以下嵌套记录值,解释[HasError]
,[Error]
以及[Message]
在之前单价实例字段查找。
复制
[
HasError = true,
Error =
[
Reason = "Expression.Error",
Message = "negative unit count",
Detail = null
]
]
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。