前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DAX 2 - 第一章 什么是 DAX

DAX 2 - 第一章 什么是 DAX

作者头像
BI佐罗
发布2020-04-27 10:24:44
4.4K0
发布2020-04-27 10:24:44
举报
文章被收录于专栏:PowerBI战友联盟PowerBI战友联盟

本文来自社区伙伴对《DAX 权威指南(第二版)》的学习笔记,有问题可以留言或联系BI佐罗修改,感谢你的支持。

DAX 即数据分析表达式,是 Microsoft Power BI、Microsoft Analysis Services 和 Microsoft Power Pivot for Excel 的编程语言。它创建于 2010 年,第一次发布了针对 Microsoft Excel 2010 的 PowerPivot。2010 年,PowerPivot 的拼写没有空格。该空格于 2013 年以 Power Pivot 的名称引入。从那时起,DAX 在 Excel 社区(使用 DAX 在 Excel 中创建 Power Pivot 数据模型)和商业智能(BI)社区(使用 DAX 在 Power BI 和 Analysis Services 中构建模型)中变得越来越流行。DAX 存在于许多不同的工具中,它们共享同一个名为 Tabular 的内部引擎。由于这个原因,我们经常引用 Tabular 模型来指代以上这些不同的工具。

DAX 是一种简单的语言。也就是说,DAX 与大多数编程语言不同,因此熟悉它的一些新概念可能需要一些时间。根据我们的经验,在向成千上万的人教授了 DAX 之后,学习 DAX 的基础知识非常简单,您将能够在几小时内开始使用它。当涉及到理解高级概念,例如计算上下文、迭代和上下文转换时,一切就会变得复杂,但不要放弃,要有耐心。当您的大脑开始消化这些概念时,您会发现 DAX 确实是一种简单的语言,只是需要一些时间来适应。

本章首先概述了数据模型在表和关系方面是什么。我们建议所有经验水平的读者阅读本节,以熟悉本书中涉及表、模型和各种关系时使用的术语。 在本章后续的部分中,还将为那些已经具有 Microsoft Excel、SQL 和 MDX 等编程语言经验的读者提供相应的建议。每个部分都聚焦于某种特定的语言,以便感兴趣的读者快速地将 DAX 与其进行比较。您只需要按你知道的语言的比较即可,然后阅读最后一节“DAX 之于 Power BI 用户”,然后再在下一章正式开始学习 DAX 语言。

[!NOTE] 对于初学者来说,你可能不会 SQL,更不会 MDX,那你完全可以跳过本章中的这些描述,因为这些描述的就在说明一件事:用 DAX 才是最合适的。

理解数据模型

DAX 是专为针对数据模型中进行业务计算而设计的。读者可能已经知道什么是数据模型。如果不知道,我们从数据模型和关系的概念出发,构建 DAX 知识体系的基础。

理解数据模型

数据模型,是若干个由关系连接的表构成。

我们都知道表是怎样的,即包含数据的若干行,每一行都被分成若干列。每一列都符合一种数据类型,并包含一个信息。我们通常将表中的一行称为记录。表是整合数据的一种方便的方法。很明显,单表是最简单的形式,它本身也算是一个数据模型。因此,当我们在 Excel 工作簿中写入名称和数字时,我们就已经在创建数据模型了。

如果一个数据模型包含许多表,那么它们可能通过关系进行连接。关系是两个表之间的连接。如果两个表之间有关系连接,我们会说这两个表是相关的。从图形上看,关系由连接两个表的线表示。图 1-1 显示了一个数据模型示例。

图 1-1 该数据模型由 6 个表组成。

以下是关系的几个重要方面:

  • 一个关系中的两张表作用是不同的。它们被称为关系的一端和多端,分别用 1 和*表示。如图 1-1 所示,Product 表和 Product Subcategory 表之间的关系。一个子类别包含许多产品,而一个产品只有一个子类别。因此,Product Subcategory 表是关系的一端,有一个子类别,在作为多端的 Product 表就有多个产品。
  • 特殊类型的关系有一对一 (1:1) 和多对多(),多对多关系又被称为弱关系。在一对一关系中,两个表都是位于一端的。而在多对多的弱关系中,两个表都可以是位于多端的,这种特殊的关系并不常见,我们将在第 15 章“高级关系”中详细讨论它们。
  • 用于创建关系的列(通常在两个表中具有相同的名称)称为关系的键。在关系的一端,列的每一行都必须是非重复的唯一值,并且不能包含空值(注意:空值与空格概念不同,空格也是值)。在关系的多端,相同的值可以在许多不同的行中重复,而且经常如此。当一列中的每一行都有一个唯一的值时,它被称为表的键(不管你有没有用它来创建关系)。
  • 关系可以形成链条。每个产品都有一个子类,每个子类都有一个类别。因此,每个产品都有一个类别。要检索产品的类别,必须遍历由两个关系组成的链。图 1-1 包括一个由三个关系组成的链的例子,从 Sales 开始,一直到 Product Category。
  • 在每一种关系中,一个或两个小箭头可以确定相互筛选的方向。图 1-1 显示了 Sales 和 Product 之间关系中的两个箭头,而所有其他关系都有一个箭头。箭头表示关系自动筛选的方向(或交叉筛选)。由于确定正确的筛选方向是最重要的学习技能之一,我们将在后面的章节中更详细地讨论这个主题。我们通常不鼓励使用双向筛选,如第 15 章所述。它们出现在这里的模型中只是为了教学目的。

理解关系的方向

每个关系都可以有一个单向或双向的交叉筛选。筛选总是从关系的一端进行到多端。如果交叉筛选是双向的,也就是说,如果它有两个箭头,筛选也发生在从多端到一端。

一个例子会帮助理解这种行为。如果报表基于图 1-1 所示的数据模型,年份在行上,并且 Quantity 和 Count of Product Name 在值区域,则生成如图 1-2 所示的结果。

[!NOTE] 这里的报表一词,和透视表同义。指的是具体的一个图表,而非整个页面。

图 1-2 此报告显示的是跨越多表进行筛选的效果。

Calendar Year(日历年份)位于 Date 表的列。Date 日期表的关系是一端到 Sales 销售表的多端,引擎会根据年份对 Sales 表进行相应的年份筛选。因此上图 Quantity 数量按年度显示。

然而对于产品表而言,情况又有些不一样。因为 Sales 表和 Product 表之间是双向关系。若将产品名称的数量放入报表,可获得每年销售的产品数量,因为通过 Sales 销售表的关系传递,Product 产品被相应的年份所筛选。如果 Sales 表和 Product 表之间是单向关系,那么结果会有所不同,如下一小节所示。

如果我们调整报表,将 Color(颜色)放入行标签,将 Count of Date(日期数量)放入值区域,结果发生变化,如图 1-3 所示:

图 1-3 如报表所示,若表的关系不是双向筛选关系,表无法显示筛选结果

如图位于行上的 Color 字段对应 Product 产品表的 Color 颜色列,因为 Product 产品表单向关系对应 Sales 销售表,Quantity 数量正确地显示了筛选后的结果。Count of Product Name(产品名称计数)显示的是筛选后结果,因为它和 Color 来自同一个表(即产品表)。Count of Date(日期计数)可能出乎初学者意料,每一行显示的都是相同的数值,实际上,这个相同的数值是日期表的总行数。

因为日期表和销售表是单向关系,颜色列的筛选并没有传递到日期表。因此,尽管销售表已经被筛选,单向关系类型导致该筛选不能传递至 Date 表。

如果我们将日期表和销售表之间的关系调整为双向关系,结果图如 1-4 所示:

图 1-4 如果我们启用双向关系,日期表的筛选结果可以正确显示

DAX之于Excel用户

您可能已经知道 DAX 和 Excel 函数有些相似。毕竟,Excel 的 Power Pivot 是在 DAX 起源时便开始使用,开发团队也试图让 Excel 函数和 DAX 相似。这种相似性让我们更加容易学习 DAX。不过,DAX 和 Excel 函数还是有一些根本性区别的。

单元格与表

Excel 在单元格中执行计算。使用坐标引用单元格,编写如下公式

代码语言:javascript
复制
= (A1 * 1.25) - B2

在 DAX 中,没有像单元格和坐标这样的概念。单元格不适用于 DAX,而表和列可以。因此,DAX 表达式引用表和列,意味着全新的编写代码方式。然而,引用表和列在 Excel 中已经出现过。如果我们通过“表格”功能将 Excel 范围定义为表格,Excel 就可以引用表格和列来编写公式。在图 1-5 中,SalesAmount 列中计算的表达式没有引用工作簿中的单元格,而是引用该表的列:

图 1-5 Excel 可以引用表格的列

在 Excel 中,我们使用[@列名称]的格式来引用表的列,列名称是需要引用的列的名称,@符号表示”获取当前行的值“,因为语法不直观,我们通常不会这样写,单击单元格时,Excel 会插入正确的代码。

你可能认为 Excel 有两种不同的计算方式,我们可以标准引用单元格,单元格 F4 的公式显示为 E4*D4,或者在表中引用列。引用列有如下优点,列的所有单元格都是相同的表达式,Excel 会根据每一行不同的值来计算公式。

和 Excel 不一样,DAX 只能够在表中运行,所有的公式必须引用表内的列,举一个例子,在 DAX 里我们会这样写之前的乘法:

代码语言:javascript
复制
Sales[SalesAmount] = Sales[ProductPrice] * Sales[ProductQuantity]

可以发现每一列名都以表名称为前缀。在 Excel 中,公式仅在这个表中运行,我们不需要添加表前缀。但是,DAX 需要对数据模型里的许多表进行操作,因此,我们必须特别指明表名(可能不同表中的两列的列名相同)。

DAX 的很多功能的运行方式和 Excel 一模一样,比如,DAX 里 If 函数的读法和 Excel 一样:

代码语言:javascript
复制
IF ( [@SalesAmount] > 10, 1, 0)
代码语言:javascript
复制
IF ( Sales[SalesAmount] > 10, 1, 0)

Excel 和 DAX 的重要区别在于两者引用整列的语法方式不同,在[@产品数量]里,@表示“当前行的值”,而 DAX 不需要特别指出值来自于该行,因为逻辑默认就是这样的。Excel 可以用所有列的概念,也就是该列的所有行,如果将“@”符号删除,你会发现结果如图 1-6 所示:

图 1-6 Excel 可以通过在列名称前省略@符号,从而引用此列中的所有行

AllSales 列是销售额列的所有值的总计,所以 AllSales 列的所有行都是同一个值。换句话说,所在列的当前行的值,与将所在列的所有行的总计值的语法是不一样的。

DAX 是不一样的,图 1-6 的销售总计在 DAX 中是这样写的:

代码语言:javascript
复制
AllSales := SUM ( Sales[SalesAmount] )

在特定某行取值与将整列视为整体取值,两者的语法没有区别。因为我们在聚合函数中用了列名称(此例聚合函数为 SUM 函数),这让列名变成一个整体参数,导致 DAX 认为我们要这一列的所有值的总和。因此,尽管 Excel 需要一个清晰的语法,来区分要检索的两种类型的数据,DAX 会自动消除语法歧义。至少刚开始接触,这种差异可能会被混淆。

Excel与DAX:两种函数语言

Excel 和 DAX 的写法是类似的,两者都是函数式语言。函数式语言由函数调用构成的表达式组成。尽管语句,循环和跳转这些概念经常在许多编程语言中看到,Excel 和 DAX 是没有这些概念的。DAX 的世界里,所有都是表达式。这对于掌握其他编程语言的程序猿来说是一个挑战,但对所有 Excel 用户来说,这一点都不奇怪。

DAX中的迭代运算

迭代的概念对你而言可能是陌生的。Excel 里,一次只能执行一次计算(没有迭代)。前面的例子展示计算销售总额,我们新建一个价格乘以数量的列,随后我们对其求和,计算销售总额。得出的数字可作为分母,用来计算每种产品的销售百分比。

在 DAX 里,你可以使用迭代器在一个步骤中执行相同的操作,迭代器的工作方式正如其名:迭代表,并对表的每一行进行计算,将结果予以汇总,返回需要的单个值。

[!NOTE] 迭代是一个动词,指对某集合的元素依次访问,通常在迭代访问时,会进行一些操作。在 DAX 中,这个集合就是表,而集合的元素就是表中的行。而迭代器是一个名词,指可以进行迭代动作的函数。

通过之前的例子,我们现在能够用 SUMX 迭代器来计算销售额:

代码语言:javascript
复制
AllSales :=
SUMX (
    Sales,
    Sales[ProductQuantity] * Sales[ProductPrice]
)

这种方法既有优点也有缺点,优点是你不用担心添加辅助列,一个步骤中就可以执行许多复杂的运算。缺点是,与用 Excel 函数编写相比,DAX 编写的视觉效果不够直观。实际上,你看不到计算价格乘以数量的列,它仅在计算的中间过程中存在。

这个我们稍后会解释,我们可以创建一个计算列,来计算价格和数量的乘积。然而,这样做不是一个好方法,因为这会占用内存,降低计算效率,这个我们会在第 18 章”优化 VertiPaq”中提到。

DAX需要的理论

我们需要明确的事实:DAX 首先需要学习的,不是它和其他编程语言有何不同,而是思维模式的转变。遇到一些待解决的问题时,你可能已经习惯在网上找复杂的公式和解决方案去解决。在 Excel,你可能会找到一个几乎满足你需求的公式。复制,根据需求微调,不用想这个公式的运行原理就可以直接用了。

这个方法适用于 Excel,但不适用于 DAX。你需要研究 DAX,真正理解什么是计算上下文后,才会写出好的 DAX 代码。如果没有好的理论基础,你会感觉 DAX 要么像变魔术一样来计算值,要么计算出一堆不知所云的奇怪数字。这不是 DAX 的问题,而是你完全不知道 DAX 是怎么运行的。

幸运的是,DAX 的理论仅有两个重要概念,我们会在第四章“理解计算上下文”中解释,在读第四章时,做好吃透的准备,等你完全掌握这个内容,也就了解 DAX 了,DAX 主要是通过经验的积累来进行学习,记住:掌握是成功的一半。因此,真正掌握计算上下文后,再继续深入学习。

DAX之于SQL开发者

如果你已经熟悉 SQL 语言并做了很多表,在列与列之间创建连接来建立关系。从这点来看,DAX 的世界对你来说驾轻就熟。的确,DAX 的计算是一个在很多建立关系的表中进行查询,将其汇总的过程。

处理关系

SQL 和 DAX 第一个不同之处是模型里关系的工作方式。在 SQL 中,我们可以在表之间设置外键来声明关系,但如果我们不明确声明,在查询里,引擎不会使用这些外键。举一个例子,如果我们有一个销售表一个客户表,客户键是在客户表是主键,在销售表是外键,写出如下查询:

代码语言:javascript
复制
SELECT
  Customers.CustomerName,  SUM ( Sales.SalesAmount ) AS SumOfSalesFROM
  Sales  INNER JOIN Customers    ON Sales.CustomerKey = Customers.CustomerKeyGROUP BY
  Customers.CustomerName

尽管在模型里,我们用外键来声明关系,查询中依旧需要明确声明并说明连接条件。虽然这样做会把查询变的冗长,但这样做很有用,因为你可以在不同的查询中使用不同的连接条件,表达查询的方式拥有更大的自由度。

DAX 中,关系是模型的一部分,所有的关系都是左外连接。模型里定义关系的时候,你不再需要在查询中指定查询类型:在查询中只要你使用与主表相关的列,DAX 都会自动使用左外连接。因此,在 DAX 里,之前的 SQL 查询你会这样写:

代码语言:javascript
复制
EVALUATE
SUMMARIZECOLUMNS (
    Customers[CustomerName],
    "SumOfSales", SUM ( Sales[SalesAmount] )
)

因为 DAX 知道“销售”和“客户”之间的现有关系,所以它会按照模型自动进行关联。最后,SUMMARIZECOLUMNS 函数需要按 Customers [CustomerName]执行分组。

DAX是一个函数语言

SQL 是一种声明语言。你不用想引擎是如何返回信息,把需要的数据集进行声明,将其定义,用 SELECT 语句检索返回。

然而,DAX 是一个函数语言,DAX 的每一个表达式都是一系列函数调用。一个函数参数又可以是其他函数调用,这样的参数会将查询变的复杂,DAX 执行查询后获得计算结果。

举一个例子,如果我们想知道哪些客户住在欧洲,SQL 的查询会这样写:

代码语言:javascript
复制
SELECT
  Customers.CustomerName,  SUM ( Sales.SalesAmount ) AS SumOfSalesFROM
  Sales  INNER JOIN Customers    ON Sales.CustomerKey = Customers.CustomerKeyWHERE
  Customers.Continent = 'Europe'GROUP BY
  Customers.CustomerName

用 DAX 的话,我们不用在查询中声明“在哪里”的条件,而我们需要一个特殊的函数: Filter,来获得筛选后的结果:

代码语言:javascript
复制
EVALUATE
  SUMMARIZECOLUMNS (
    Customers[CustomerName],
    FILTER (
        Customers,
        Customers[Continent] = "Europe"
    ),
  "SumOfSales", SUM ( Sales[SalesAmount] )
)

你会发现 Filter 是一个函数:它返回了只住在欧洲的客户,获得了我们希望的结果。函数嵌套的顺序和函数的选用,对 DAX 的运行结果都有影响。SQL 也有这样的情况。SQL 的查询优化器会找到查询更优解,DAX 的话,尽管 DAX 的查询优化器也做的不错,而你,作为编写者,最好承担更多的责任,而不要指望 DAX 引擎对此的自动优化能力。

DAX作为编程语言和查询语言

SQL 作为查询语言和作为编程语言,其表现存在一个清晰的分界线——在数据库中创建存储过程,视图和其他代码段的指令集,SQL语句的体现方式不同,程序员用代码来完善数据模型。然而,DAX的查询和编程在形式上是没有区别的。各种各样的函数将表进行转换后,再以表的形式返回。前面查询中的Filter函数就是一个很好的例子。

在这一点上,可以看出 DAX 比 SQL 的形式更加简单,若你将其作为一个编程语言(它最开始的用途)来学习,你会发现,其中所有相关的知识也适用于查询语言。

DAX和SQL的子查询和条件

作为查询语言,子查询是 SQL 最强大的功能之一。DAX 也有类似的概念。然而 DAX 的子查询是通过语句来表现的。

举一个例子,如果想知道购买总额超过 100 美元的顾客与其具体的购买金额,在 SQL 的查询中这样写:

代码语言:javascript
复制
SELECT
  CustomerName,
  SumOfSalesFROM (  SELECT
    Customers.CustomerName,    SUM ( Sales.SalesAmount ) AS SumOfSales  FROM
    Sales    INNER JOIN Customers      ON Sales.CustomerKey = Customers.CustomerKey  GROUP BY
    Customers.CustomerName
  ) AS SubQueryWHERE
  SubQuery.SumOfSales > 100

通过调用嵌套函数,在 DAX 中我们得到相同的结果:

代码语言:javascript
复制
EVALUATE
FILTER (
  SUMMARIZECOLUMNS (
      Customers[CustomerName],
      "SumOfSales", SUM ( Sales[SalesAmount] )
  ),
  [SumOfSales] > 100
)

如上这段代码中,子查询将 CustomerName 和 SumOfSales 所返回的值,再次赋入 Filter 函数,Filter 函数保留其中销售总额大于 100 的值。现在,你可能看不懂这段代码,不过你学习 DAX 后,你会发现 DAX 的子查询比 SQL 的简单的多, 而且因为 DAX 是函数式语言,读起来也更顺畅。

DAX之于MDX开发用户

因为 DAX 是 Tabular 的新语言,许多专业商业智能用户开始学习它。以前,分析服务多维模型(Analysis Services Multidemensional)是用 MDX 语言构建查询的。如果你以前用的是 MDX,做好从头学 DAX 的准备,因为 DAX 和 MDX 几乎没有相似的地方。更糟糕的是,DAX 的一些概念会让你联想到 MDX 的一些概念(但两者完全不同)。

以往经验来看,掌握 MDX 的情况下再学 DAX 是一件非常难的事情。你需要将 MDX 的已有知识清空,再去学 DAX。把之前你知道的多维空间知识都忘掉,重新去学习这门新语言。

[!NOTE] 就像学习两个门派的武功,有武功的人总会自己认为再掌握一门武功是容易的,然后对于 DAX 来说,忘记以前所学的,才是入门的第一要务。

多维模式 vs. 表模式

MDX 在模型定义的多维空间里运行。多维空间的形状取决于数据模型定义的层次结构和数据结构,反过来,层次结构和数据结构又定义了多维空间的坐标集。不同维度中,成员集的交集定义多维空间的点。可能你需要点时间去理解:任何属性层次结构的[all]成员,实际上是多维空间的一个点。

DAX 就没那么复杂了。DAX 没有维度,没有成员,没有多维空间的点。也就是说,DAX 压根没有多维空间这个东西。DAX 的层次在模型里定义,但是 DAX 的模型和 MDX 的不一样。DAX 空间建立在表,列和关系上。每个 Tabular 模型里的表,既不是度量组也不是维度,它是一个可以计算值,扫描,筛选,对里面的值进行求和的表。DAX 的一切都基于两个简单的概念:表和关系。

你很快就发现,在建模这一块,Tabular 的选择比多维空间少。然而,选项少并不意味着功能少,因为你可以用 DAX 的编程语句来补充模型。Tabular 建模的真正能力在于 DAX 的速度。你可能在模型中,需要尽可能避免过度使用 MDX,因为优化 MDX 的速度是一件很难的事。然而 DAX 就不一样了,它的速度惊人的快。所以,在 DAX 公式中进行大多数的复杂计算,而不是在模型。

作为编程语言和查询语言的DAX

DAX 和 MDX 是编程语言,也是查询语言。MDX 可以通过脚本,来区分编程语言和查询语言。在 MDX 脚本中使用的是 MDX 语言,有几个特殊语句,比如 SCOPE 语句,只能在脚本中使用。用 MDX 检索时,用 SELECT 语句来返回数据。DAX 的话,就有些不一样。

DAX 可以作为编程语言来定义计算列,计算表和度量值。DAX 新提出的计算列和计算表的概念,MDX 里面没有。DAX 的度量值和 MDX 的计算集合类似。

DAX 也可以作为查询语言,举一个例子——用报表服务来返回Tabular模型的值。

因此,DAX 对于编程或查询没有区别,它在查询和编程里使用是完全一致的。更进一步的是,你还可以用 MDX 查询由 DAX 构建的 Tabular 模型。当然,构建 Tabular 模型时,只能使用 DAX。

层次

[!NOTE] 这里是对 MDX 更深层应用的描述,DAX 初学者根本不需要了解。

MDX 中,你依靠层次来进行大部分的运算。如果想知道前一年的销售,你需要在 Year 的层次结构检索位于 CurrentMember 的 PrevMember, 检索出 PrevMember 后,覆盖 MDX 过滤器。比如,在 MDX 里定义前年的计算,会像如下这样写:

代码语言:javascript
复制
CREATE MEMBER CURRENTCUBE.[Measures].[SamePeriodPreviousYearSales] AS
(
  [Measures].[Sales Amount],
  ParallelPeriod (
    [Date].[Calendar].[Calendar Year],
    1,
    [Date].[Calendar].CurrentMember
  )
);

度量值使用 ParallelPeriod 函数,函数返回 Calendar 层次结构上 CurrentMember 的表亲。因此,它基于模型中定义的层次结构。

同样的计算用 DAX 的筛选上下文和时间智能函数来写,如下:

代码语言:javascript
复制
SamePeriodPreviousYearSales :=
  CALCULATE (
    SUM ( Sales[Sales Amount] ),
    SAMEPERIODLASTYEAR ( 'Date'[Date] )
)

通过 Filter 函数和其他的函数,还有很多其他的方法来达到相同的计算效果,但是核心是一样的:用筛选表的方法,而不是用层次的方法。这两者的差异很大,在你还没习惯 DAX 时,你可能会想用层次结构计算。

另外重要的一点差异是:MDX 引用[Messures]. [Sales Amount],模型定义了你需要使用的聚合函数。DAX 不会提前定义聚合。你可能已经注意到了,计算的表达式是 SUM(Sales[SalesAmount]),模型不会有提前聚合,因为你需要的时候就会及时定义,我们永远可以随时创建计算销售额的度量值,不过这个内容已经超出本章范围,我们会在书的后面内容讲到。

还有一个 DAX 和 MDX 的差异,很重要:MDX 过多的使用 SCOPE 语句来实现业务逻辑(同样,需要使用层次结构)。而 DAX 用的完全是另外一个套路,DAX 语言里,压根没有层次结构这一说。

比如说,如果我们要清除 Year 级别的度量值,MDX 里需要这样写:

代码语言:javascript
复制
SCOPE ( [Measures].[SamePeriodPreviousYearSales], [Date].[Month].[All] )
  THIS = NULL;
END SCOPE;

DAX 没有像 SCOPE 语句这样的东西,为了获得同样的结果,我们需要确认筛选上下文中的筛选器,语句则变的更复杂:

代码语言:javascript
复制
SamePeriodPreviousYearSales :=
IF (
  ISINSCOPE ( 'Date'[Month] ),
  CALCULATE (
    SUM ( Sales[Sales Amount] ),
    SAMEPERIODLASTYEAR ( 'Date'[Date] )
  ),
  BLANK ()
)

上面的式子表示,只有客户在浏览月份级别或更低的界别的日历层次结构时,这个公式才返回值。否则,返回空值。稍后你会详细的学习这个公式。和等效作用的 MDX 相比,DAX 更容易出错。老实说,层次结构处理是 DAX 真正缺少的功能之一。

叶级计算

最后,用 MDX 的时候,你可能已经习惯于避免叶级计算。你习惯提前计算值,将得出的值进行聚合返回结果,因为 MDX 的叶级计算很慢。而 DAX 的叶级计算速度非常快,不过 DAX 的聚合有其他的用途,且仅对大型数据集有效。因此,在搭建数据模型时,需要一些观念的转换。大多数情况下,适用于 SSAS 多维的数据模型,不适用于表格模型,反之亦然。

DAX之于Power BI使用者

如果您跳过前面的部分直接来到这里,欢迎!DAX 是 Power BI 的原生语言,如果您没有 Excel,SQL 或 MDX 的经验,Power BI 将是您接触 DAX 的第一个地方。如果您以前没有使用其他工具构建模型的经验,您将了解到 Power BI 是一个功能强大的分析和建模工具,DAX 是非常棒的伙伴。

如果您刚刚开始使用 Power BI,并想进一步学习与了解,那么 DAX 将助您事半功倍。

以下是我们给您的建议:不要期望能在几天内编写复杂的 DAX 代码。掌握 DAX 需要一定练习,因此您需要投入时间和精力。根据我们的经验,一开始当您掌握了一些简单的计算时,您可能会学习热情高涨,但一旦开始学习计算上下文和 CALCULATE(DAX 语言中最复杂的主题),一切看起来都很复杂,您的学习热情可能会减退,但请不要放弃,这是大多数 DAX 学习者必经的阶段,当您学到这些章节,您已经非常接近完全理解 DAX 语言了,放弃将非常可惜。您需要反复阅读和练习,因为一日不练十日空。您可以快速学完本书,达到 DAX 大师级别。

计算上下文是 DAX 语言的核心,需要您花时间理解和掌握,鲜有人能在几天内掌握所有关于 DAX 的知识。此外,与任何复杂的主题一样,随着时间的推移,您将发现本书中诸多细节之美。当你认为自己掌握了所有东西时,请再次阅读本书。您会发现当您对内容有了更为深入的理解时,之前许多看似不那么重要的细节将会有更深刻的内涵。

好好享受本书的其他部分吧!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PowerBI战友联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 理解数据模型
    • 理解数据模型
      • 理解关系的方向
      • DAX之于Excel用户
        • 单元格与表
          • Excel与DAX:两种函数语言
            • DAX中的迭代运算
              • DAX需要的理论
              • DAX之于SQL开发者
                • 处理关系
                  • DAX是一个函数语言
                    • DAX作为编程语言和查询语言
                      • DAX和SQL的子查询和条件
                      • DAX之于MDX开发用户
                        • 多维模式 vs. 表模式
                          • 作为编程语言和查询语言的DAX
                            • 层次
                              • 叶级计算
                              • DAX之于Power BI使用者
                              相关产品与服务
                              腾讯云 BI
                              腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档