1.2 DAX FOR EXCEL用户
第1章 什么是DAX?
1.1 理解数据模型
1.2 DAX FOR EXCEL用户
1.3 DAX for SQL开发人员
1.4 DAX for MDX开发人员
1.5 DAX FOR POWER BI 用户
DAX FOR EXCEL用户
您可能已经知道DAX有点像的Excel公式语言。毕竟,DAX的根源是Power Pivot for Excel,开发团队试图使这两种语言保持相似。这种相似性使得向这种新语言的过渡更加容易。但是,有一些重要的区别。
单元格与表格
Excel对单元格执行计算。使用其坐标引用单元格。因此,我们可以编写如下公式:
= (A1 * 1.25) - B2
在DAX中,不存在单元格及其坐标的概念。DAX适用于表和列,而不适用于单元格。因此,DAX表达式引用表和列,这意味着编写代码的方式有所不同。
表和列在Excel中的不是新概念。实际上,如果通过使用" 格式为表格" 功能将Excel范围定义为表格,则可以在Excel中编写引用表格和列的公式。在图1一5中,SalesAmount列计算表达式引用同一个表中的列,而不是引用工作簿中的单元格。
图1-5 Excel可以引用表中的列名使用Excel,我们使用[@ColumnName]格式引用表中的列。ColumnName是要使用的列的名称,@符号表示"获取当前行的值"。尽管语法不直观,但是通常我们不编写这些表达式。它们在我们单击单元格时出现,Excel会为我们插入正确的代码。
您可能会认为Excel具有两种不同的执行计算方式。我们可以使用标准单元格引用,在这种情况下,F4的公式为E4 * D4,或者我们可以在表中使用列引用。使用列引用具有以下优点:我们可以在列的所有单元格中使用相同的表达式,并且Excel计算公式将为每一行返回不同的值。
与Excel不同,DAX仅适用于表。所有公式都必须引用表中的列。例如,在DAX中,我们以这种方式编写先前的乘法:
Sales[SalesAmount] = Sales[ProductPrice] *
Sales[ProductQuantity]
如您所见,每列都以其表名作为前缀。在Excel中,我们不提供表名,因为Excel公式在单个表中起作用。但是,DAX在包含许多表的数据模型上工作,所以,我们必须指定表名,因为不同表中的两列可能具有相同的名称。
DAX中的许多功能与等效的Excel功能以相同的方式工作。例如,IF函数在DAX和Excel中的读取方式相同:
Excel IF ( [@SalesAmount] > 10, 1, 0)
DAX IF ( Sales[SalesAmount] > 10, 1, 0)
Excel和DAX的语法不同的一个重要方面是引用整个列的方式。实际上,在[@ProductQuantity]中,@表示"当前行中的值"。在DAX中,无需指定一个值必须来自当前行,因为这是该语言的默认行为。在Excel中,我们可以通过删除*@ *符号来引用整个列(即该列中的所有行)。您可以在图1一6中看到这一点。
图1-6 在Excel中可以通过在列名之前省略@符号来引用整个列AllSales列的值在所有行中都相同,因为它是SalesAmount列的总计。换句话说,在当前行中的列的值与整个列的值之间在语法上存在差异。
DAX是不同的。在DAX中,这就是您编写*AllSales *的表达式,如图1一6 :
AllSales := SUM ( Sales[SalesAmount] )
检索特定行某列的值与使用整列之间在语法上没有区别。DAX理解我们要对列的所有值求和,因为我们在聚合器(在本例中为SUM函数)中使用了列名,将列名作为参数传递。因此,尽管Excel需要明确的语法来区分要检索的两种类型的数据,但DAX会自动进行歧义消除。至少在开始时,这种区分可能会造成混淆。
Excel和DAX:两种功能语言
两种语言相似的一个方面是Excel和DAX都是功能语言。功能语言基本上是由函数调用的表达式组成。在Excel和DAX中,语句、循环和跳转的概念不存在,尽管它们在许多编程语言中都是通用的。在DAX中,一切都是表达式。对于使用不同语言的程序员来说,语言的这一方面通常是一个挑战,但是对于Excel用户而言,这一点都不奇怪。
DAX中的迭代器
迭代器的概念可能对您来说是一个新概念。在Excel中工作时,您一次只能执行一次计算。前面的示例表明,要计算销售总额,我们创建一个包含价格乘以数量的列。然后,作为第二步,我们对其求和以计算总销售额。然后这个数字才能用作计算每个产品销售百分比的分母。
使用DAX,您可以使用迭代器在单个步骤中执行相同的操作。迭代器完全按照其名称的含义进行操作:迭代表并在表的每一行上执行计算,将结果汇总以产生所请求的单个值。
使用前面的示例,我们现在可以使用SUMX迭代器计算所有销售额的总和:
AllSales :=
SUMX (
Sales,
Sales[ProductQuantity] *
Sales[ProductPrice]
)
这种方法揭示了优点和缺点。优点是我们可以在一个步骤中执行许多复杂的计算,而不必担心添加只会对特定公式有用的列。缺点是,与使用Excel进行编程相比,使用DAX进行编程的视觉效果更差。
确实,您没有看到计算价格乘以数量的列;它仅在计算的生命周期中存在。
正如我们将在后面解释的那样,我们可以创建一个计算列来计算价格乘以数量的乘积。
但是,这样做并不是一个好习惯,因为它会占用内存,并且可能减慢计算速度,除非如第18章 " 优化VertiPaq "所述,您可以使用DirectQuery和聚合。
DAX需要理论
让我们清楚一点:DAX首先需要学习理论的事实与编程语言之间没有区别。这是心态上的差异。面对要解决的问题,您可能习惯于在网络上搜索要解决的方案的复杂公式。使用Excel时,您可能会发现一个几乎可以满足您需要的公式。您可以复制公式,根据需要对其进行自定义,然后使用它,而不必担心它的工作原理。
但是,这种方法在Excel中有效,却不适用于DAX。您需要学习DAX理论并彻底了解评估上下文如何工作,然后才能编写好的DAX代码。如果您没有适当的理论基础,则会发现DAX要么计算像变魔术似的计算,要么计算没有意义的奇怪数字。问题不在于DAX,而是您尚未完全了解DAX的工作原理。
幸运的是,DAX背后的理论仅限于几个重要概念,我们将在第4章 " 理解评估环境 "中进行解释。当您到达该章时,请做好一些深入学习的准备。掌握了这些内容之后,DAX对你来说将不再有秘密,而学习DAX则主要是获得经验。记住:了解是成功的一半。因此,除非您精通评估上下文,否则请不要尝试进一步。