01 零基础入门DAX

01 零基础入门DAXDAX DataAnalysis 是一种公式语言 它允许用户在 PowerPivot 表 计算列 和 Excel 数据透视表 度量值 中定义自定义计算

大家好,欢迎来到IT知识分享网。

01 认识DAX

什么是DAX

在这里插入图片描述
DAX的简单和复杂
微软在官方的介绍中称 DAX 是一种简单的语言。也就是说,DAX 的基本知识简单易学:你可以在几小时内开始使用。这确实是事实,微软在开发 DAX 的时候从 Excel 中移植了很多函数,它们名称相同,参数用法也类似。但我想告诉你的是,这种简单仅限于起步阶段。DAX 和大多数编程语言不同,它有很多独特且重要的理论,一旦涉及到这些概念,比如计值上下文、迭代和上下文转换,一切都将变得复杂起来。但不要放弃!请保持耐心。一旦你的大脑开始理解这些概念,你就会发现 DAX 确实是一种简单的语言,只是需要时间去适应。

学习 DAX 的误区
不同于其他语言,DAX 需要你理解它的原理之后才能熟练使用,如果你习惯于通过学习具体的函数建立起一门语言的知识体系(比如 Excel 函数),请千万不要将这种习惯带入到 DAX 的学习中。因为它的一些原理很难通过归纳法(从具体实例推导出普遍规律的一种方法)来理解。例如,对计值上下文(The Evaluation Context)的理解需要用到演绎推理:先接触理论本身,然后通过案例加深对理论的理解。我知道许多人不习惯这种学习方式,他们更喜欢在实践中学习,先研究如何解决具体问题,然后通过不断的练习和积累,归纳出公式背后的原理。如果你使用这种方式学习,会常常发现写出的公式能得出正确结果,但自己却不明白为什么。
在这里插入图片描述
以我的观察,有太多的学习者在这上面走了弯路,他们把之前学习其他语言的方法套用在 DAX 上,以为只要学会了函数也就掌握了这门语言。所以在这里我还想再强调一次,函数本身并不复杂,真正的复杂性蕴含于 DAX 公式的计值过程中,在简单的计算中你可以忽略它的存在,而一旦问题变得复杂,公式的计值流就会开始变得难以理解。


DAX 引擎
DAX 的能力蕴含在 SSAS 表格模型的引擎,我们称之为 VertiPaq 引擎,这是它在开发阶段的工程名称,大家已经习惯用这个名称代替它的官方用名「xVelocity 内存分析引擎」。

Vertipaq 是基于内存的列式数据库引擎,模型的所有数据都驻留在内存中。在 Vertipaq 引擎内部,数据以列式存储,而传统的 SQL 数据库引擎通常使用行式存储。简单的说,行式存储适合进行事务处理(OLTP),比如增删改查。而列式存储则适合分析决策(OLAP),比如多维分析。

DAX 能分析多少数据
你已经了解了这颗引擎的强大之处,它绝不是吃素的,它带给你的一个直观感受就是数据处理能力的飞跃
在这里插入图片描述
1 Excel:将 Excel自身的数据处理能力提升到了前所未有的高度,复杂公式几千行数据就跑不动?vlookup 几万条就开始卡顿?不存在的,Power Pivot 让你可以轻松处理几百万乃至上千万的数据,即使一些复杂的计算逻辑,DAX 引擎也能在眨眼间完成计算。
2 Power BI Desktop:引擎版本比 Power Pivot 更高,性能也有所提升,不过这种提升不太容易被量化。一般来说,处理相同数据量级和复杂度的分析,比 Excel 表现要好。
3 SSAS:具备完整的 DAX 引擎,处理能力最强




用于DAX学习的书籍

有这么一本书,在英文世界中被奉为学习 DAX 的经典必读书目,权威程度超过微软官方文档。它的知识框架足够系统和全面,在广度和深度这两个层面,都是当之无愧的 NO.1。可以说读懂了这本书,你就解锁了 DAX 的所有秘密。

不过,请等一下,所有学习 Power BI 的人都需要看这本书吗?当然不是,我不想在这里贩卖焦虑,因为每个人的时间都是宝贵的,如果你只是用 Power BI 制作一些好看的图表,或者生成一个具备交互功能的报告,只要不需要用到复杂的计算逻辑,你完全可以忽略它的存在。

看到这里你可能还有疑问,我知道这本书在 DAX 领域确实很权威,但是,Power BI 不是一直宣传用鼠标拖拽一下就可以快速生成分析图表,既然这么轻松,那还有学 DAX 的必要吗?

这是个很普遍的问题,不止 Power BI,所有的自助 BI 工具都会宣传拖拽式分析的好处,拖拽式分析快速、直观、操作简单,是业务人员分析数据的福音。也是 BI 工具比编程语言高效的地方,毕竟键盘敲得再快,也没有在用户界面操作来的快。但是拖拽式分析的瓶颈也很明显,就是只能做逻辑相对简单的分析。一旦要研究复杂一些的问题,编程语言或者函数就必须介入。对于 Power BI 而言,你必须借助 DAX,所以随着使用经验的增加你会越来越发现 DAX 的重要性。

DAX 圣经第二版更新
从 2015 年的第一版到 2019 年的第二版,四年的时间 DAX 并没有太大变化,这意味着第一版的知识仍然可以信赖。那么这次更新的第二版,究竟有哪些变化呢?作者 Macro 最近发了一篇文章,对第二版更新的内容和背后的故事做了详细介绍。我简单总结了一下,供各位一窥究竟。

02 DAX基本概念

为什么使用数据模型
在对 Power BI 的错误认识中,认为它是一个数据可视化工具的大有人在,实际上 Power BI 是一个基于数据模型的工具。 它使用独有的语言(DAX)在语义层(Semantic layer)定义度量值的业务逻辑,并允许使用两种语言查询数据模型:DAX 和 MDX,后者已经成为行业标准语言。

之所以选择 DAX 和 MDX,而不是更常见的 SQL,是因为 SQL 不适合用于语义层。 在企业 BI 工具的漫长历史中,即使工具生成 SQL 查询,也不可能在 SQL 中定义通用业务规则,除非是在数据源的行级别进行非常简单的计算。

例如,假设计算利润率%需要用到两张表, 在 SQL 中定义除以两个聚合结果的通用计算是一项复杂的任务。每个工具都发明了自己的方法来解决这一问题。 用 SQL 表示这种计算需要一个非常具体的查询,并且不具有足够的通用性,不能与同一查询中的任何筛选器、聚合或其他度量值的组合一起使用。

数据建模

数据模型是什么
模型对于 Excel 用户和数据分析的新手可能是个比较陌生的概念,但我想大部分人应该都听说过以下这些模型:回归模型、分类模型、决策树模型、朴素贝叶斯模型。
在这里插入图片描述
它们都属于算法模型的范畴,实现了 输入- 处理 – 输出 这样一个过程。算法模型用途广泛,但不是这里要讨论的内容,我们介绍的是另一种模型:数据模型,数据模型是现实世界的抽象,举个例子:超市昨天一共产生多少笔订单,每笔订单包含哪些商品,每种商品又由哪些原材料构成。我们把这些数据记录到表中,再导入数据库。这个时候你通过查询数据库就可以掌握超市的运营情况,单表可以视为结构简单的模型,通常我们研究的是基于多张表的模型,这时就引入了现实世界中的一个重要概念:关系。一旦表和表之间建立了关系,我们就摆脱了单表的束缚,可以在不同的表之间进行查询。你可以把关系想象成 Excel 中的 VLOOKUP,实际上关系要灵活和强大的多。
在这里插入图片描述
有哪些常用的数据模型
数据模型对于数据库使用者是一个很重要的概念,普通 BI 用户不必了解背后的所有内容,只需要掌握一些基本知识即可。





ER 模型(Entity Relationship Model)
实体关系模型,用实体加关系构成的数据模型描述企业业务架构,在范式理论上符合三范式,是站在企业角度面向主题的抽象,而不是针对某个具体业务流程的实体对象关系抽象,它更多是面向数据的整合和一致性治理,为基础数据仓库建设服务。

维度建模
星型模型和雪花模型都是维度建模中的常用模型,维度建模以分析决策的需求出发构建模型,构建的数据模型为分析需求服务,因此它重点解决用户如何更快速完成分析,同时还有较好的大规模复杂查询的响应性能,更直接面向业务。

维度模型最基本的两个要素是事实表和维度表:

星型模型:事实表位于中心,维度表直接与事实表建立关系。

在这里插入图片描述
雪花模型:经过规范化存储的维度表,多张维度表连接在一起,单表没有冗余

在这里插入图片描述
理解 Power BI 中的数据模型

DAX 是一种专门为计算数据模型中的商业逻辑而设计的语言。看完前面的介绍,你已经对数据模型有了一个初步的认识,如果你还不熟悉它,那么花些时间来介绍数据模型和关系是很有必要的,因为这些概念是你建立 DAX 知识的基石。

数据模型是一组通过关系连接到一起的表 

我们都知道什么是表:一组包含数据的行,每一行被列分割,每列都有指定的数据类型,并且只包含一种信息。我们通常将表中的一行称为记录。表是管理数据的一种简便方法,表的本身已经是一个数据模型,尽管这是最简单的形式。因此,当你在 Excel 工作簿中填写名称和数字时,你正在创建一个数据模型。

在这里插入图片描述

如果数据模型包含许多表,通常它们是通过关系连接的。关系建立在两个表之间。当两个表通过关系连接在一起时,我们说它们是相关联的。从图形上看,关系由连接两个表的直线表示。图 1-1 显示了一个数据模型的示例。

在这里插入图片描述

学习关系你需要了解的重要知识点:

*关系中的两个表承担不同的角色,他们被称为关系的一端和多端。*在图 1-1 中,注意 Product 表和 Product Subcategory 表之间的关系。一个子类别中包含许多产品,而单个产品只能有一个子类别。因此,Product Subcategory 表位于关系的“一”端(每行有一个子类),而 Product 位于“多”端(对应了很多产品)。

于创建关系的列(通常在两个表中具有相同的名称)称为关系的键。在关系的一端,列的每一行需要有唯一的值。在关系的多端,相同的值通常在不同的行重复出现。如果列的每一行都是唯一值,则该列被称为表的键。通常情况下,表有一个列是键列。

*关系可以形成链条。*每个产品都有一个子类别,每个子类别都有一个类别。因此,每个产品都有一个类别。为了检索产品的类别,你需要遍历两个关系链。图 1-1 包含一个由三个关系组成的关系链的示例,从销售表开始,一直到产品类别表。

在每个关系中,可以有一个或两个小箭头。在上图中,你可以看到销售表和产品表之间的关系中有两个箭头,而其他所有关系都只有一个箭头,箭头表示关系将沿着此方向自动筛选。我们会在后面的文章中会更详细地讨论这个问题,因为确定正确的筛选方向是最重要的技能之一。

为什么说星型模型是 Power BI 的最佳模型结构
上文中我们提到了一个很重要的信息*:星型模型是更适合 Power BI 建模使用的结构,*这不仅是出于减少数据冗余的考虑,因为对于列式数据库来说,即使有一定的冗余也可以被引擎很好的压缩,更主要的原因是从计算准确性角度给出的建议。虽然宽表形式(所有的维度和指标都汇总到一张表)被很多 BI 工具或者分析系统采用,但是在 Power BI 中使用这种结构,在某些计算时可能导致异常结果。

使用宽表做数据源的报表可能计算出不准确的数字,而星型模型是一种更为可靠的分析系统 

在这里插入图片描述

CountA 计算表的行数,只对数据源存在的组合返回记录,所以类似这样的搭配属于无效组合,返回空值。CountB 度量值在前者基础上增加一个内部筛选器参数,将 name 值修改为 TV,根据 CALCULATE 计值流规则,这种写法无论外部上下文中的 name 列使用哪个值,都将被 CALCULATE 替换为 TV。如果你从这个角度思考,会发现右边的结果似乎并不正确,因为它只保留一行记录,如果替换发生,那么的组合将在内部被替换为后返回 1,但结果并非如此。

不合理的模型结构带来的其他问题
单纯强调模型结构的重要性可能没法让你产生直观感受,这里我用反面案例来说明,一个糟糕的模型可能给你带来哪些问题,如果你过去习惯于在 Excel 里分析数据,那这部分内容是你需要特别关注的,很多使用者在切换到 Power BI 后,由于没有真正理解模型结构的重要性,在这上面走了很多弯路。

数据库三范式

范式是关系数据库理论的基础,也是设计数据库结构过程中所要遵循的规则和指导方法。范式的种类比较多,其中最主要的有三个范式,即:第一范式(1NF),第二范式(2NF),第三范式(3NF)

为什么要介绍范式?如果没有实地做过数据库设计、或者建模经验比较少,是不容易理解范式这种抽象概念的。但是随着你接触 Power BI 时间的增加、使用的表越来越多、表之间的关系越来越复杂,会逐渐体会到一个设计合理的模型结构是多么的重要。毫不夸张的说,很多时候写不出 DAX 公式不是因为公式用法没掌握,而是模型结构有问题。了解范式理论,有助于在建模过程中识别并纠正不合理的结构,防患于未然。

第一范式(1NF):列的原子性,保证表的每一列都是不可分割的原子项
在这里插入图片描述
所在地这一列不符合第一范式,需要拆分为下面的结构
在这里插入图片描述
第二范式(2NF):在 1NF 的基础上,非关键字段必须依赖唯一的主键
在这里插入图片描述
工牌姓名依赖于工牌编号,饭卡姓名和余额依赖于饭卡编号,两个主键违反了第二范式。如果使用这种结构,删除工牌编号记录的同时也会删除饭卡信息,这是不合理的。如果一个工牌可以办理多张饭卡,表格会产生冗余数据。所以我们需要将其拆分为工牌和饭卡两张表,这样每张表都有唯一的主键。





第三范式(3NF):在 2NF 的基础上,表中的每一列都和主键直接相关,不能存在传递依赖
在这里插入图片描述
城市人口依赖于城市,城市依赖于用户编号,城市人口与用户编号是传递依赖,违反了第三范式。解决方法是将城市相关信息拆分到一个单独的表。

主键、外键

主键的选择
数据库对主键的要求中最关键的一点是:记录一旦插入到表中,主键最好不要再修改,因为主键是用来唯一定位记录的,修改了主键,会造成一系列的影响。

由于主键的作用十分重要,如何选取主键会对模型结构产生重要影响。如果我们以用户的身份证号作为主键,似乎能唯一定位记录。然而,身份证号也是一种业务场景,如果身份证号升位了,或者需要变更,作为主键,不得不修改的时候,就会对业务产生严重影响。从存储成本的角度考虑,身份证可以作为 13 亿人的唯一身份标识,如果一家公司用它来做主键,未免有点浪费存储空间。

所以,选取主键的一个基本原则是:不使用任何业务相关的字段作为主键。因此,身份证号、手机号、邮箱地址这些看上去可以唯一的字段,严格来讲均不可用作主键。可用做主键的类型有:

联合主键
除了可以使用单列作为主键,也可以组合多列作为主键,这种就是联合主键,联合主键允许一列有重复值,只要构成联合主键的所有列的组合不重复即可。
比如 Sales 表中本身存在 OnlineSalesKey 这一主键,但是用 ProductKey 和 Order Number 也可以作为联合主键,区分唯一记录。
如何在表格模型中手动设置主键
Excel Power Pivot 和 SSAS 都支持对任意表设置主键,Power BI Desktop 目前只支持对日期表设置主键,不过你可以通过另外一种方式创建主键,在下文解决循环依赖问题时会提到。
在这里插入图片描述在这里插入图片描述




外键

一对多关系中位于关系多端的列就是外键,外键可以包含重复值。第一张图 Sales 表包含的 ProductKey 就是 Product 表的外键。通过设置关系数据库的外键约束,可以控制存储在外键表中的数据,使其不能插入主键表中不存在的记录。

  • 超键(Super Key): 在关系中能唯一标识元组的属性集称为关系模式的超键
  • 候选键(Candidate Key): 不含有多余属性的超键称为候选键,也叫最小超键。通常我们会从候选键中选择一个作为主键。
  • 代理键(Surrogate
    Key):当数据表中的候选键都不适合当主键时,例如数据太长,或是意义层面太多,就会请一个无意义的但唯一的字段来代为作主键。在实践中,代理键值通常是个自动递增的数字。
  • 自然键(Natural Key):与代理键相反,是在业务逻辑中唯一确定一个事物的标识。身份证号(理论上,假设没有因技术原因造成的重复)就是一个自然键,用于确定一个人。

索引

在关系数据库中,如果有上万甚至上亿条记录,在查找记录的时候,想要获得非常快的速度,就需要使用索引。索引是关系数据库中对某一列或多个列的值进行预排序的数据结构,可以让数据库系统不必扫描整个表,而是直接定位到符合条件的记录,这样就大大加快了查询速度。

参照完整性

表格没有空白行,切片器里面怎么会有空白项 

在这里插入图片描述
这个问题曾经困扰过很多人:

我的数据中明明没有空白,为什么制作报表的时候,筛选器和图表有时会显示一条空白记录?

空白当然不是凭空产生的,它遵循一定的规律,这篇文章我们来介绍空白项产生的原因,也就是参照完整性

关系模型的三类完整性约束

数据库关系模型中有三类完整性约束,分别是:实体完整性,参照完整性,用户定义完整性

实体完整性
用于保证关系数据库中每条记录都是可区分的,唯一的,这种唯一既不能有重复值,也不能有空值。在主键 外键和索引中我们介绍过,这其实就是主键的作用,因此,从便于记忆的角度,你也可以理解为主键完整性。

用户定义完整性
不同的关系数据库因其应用环境的不同,通常需要针对某一具体字段设置约束条件,这种由使用者基于具体业务逻辑设定的约束条件,就叫做用户定义完整性。比如学生的性别字段只能有男、女两个值,学生考试成绩的范围是 0-100 分。

参照完整性

参照完整性,又称引用完整性,是相关联的两个表之间的约束,对于建立关系的两个表来说,事实表每条记录中的外键必须是主表中存在的,简单的说,就是事实表的每一行必须在维表中存在对应的记录。

以下表为例,位于关系多端的 Orders 表的外键 CustomerID 存在一条记录[CustomerID = CustX]与维表不匹配,这种情况下以 DIM_A 表的 Customer 列建立筛选器(文章开头的图片),会显示一条空白记录。

在这里插入图片描述
Power BI 允许违反参照完整性的情况出现,而在数据库系统中,如果两个表之间建立了关联关系,对关系的操作会影响到另一个表中的记录,此时参照的完整性不允许关系中有不存在的实体引用。参照完整性与实体完整性二者,皆是关系模型必须满足的完整性约束条件,其目的在于保证数据一致性。

Power BI 中的参照完整性

假设引用完整性对性能的影响
在直连模式下(DirectQuery),使用假设引用完整性可以获得更好的性能表现,如果感觉直连模式下查询缓慢,请检查此设置是否开启。

数据类型和运算符

数据类型
DAX 可以使用七种常用的数据类型进行计算。在下面的列表中,我们展示了同一种数据类型在 DAX 种的名称和它更常见的名称。例如,布尔值(Boolean values)在 DAX 术语中被称为 TRUE/FALSE。我们更愿意遵循事实上的命名标准,将它们称为布尔值。除此之外,还有两种比较特殊的类型会在最后介绍

整数 (Integer)
DAX 只有一个整数数据类型,存储 64 位的整数。DAX 中的整数值之间的所有内部计算都使用 64 位整数。 它支持 19 位数;从 -9,223,372,036,854,775,807 (-2^63+1) 到 9,223,372,036,854,775,806 (2^63-2) 的正数或负数。 在需要控制舍入的情况下,整数类型非常有用。

十进制数(Float)
十进制数总是以双精度浮点值的形式存储。不要将这种 DAX 数据类型与 Transact-SQL 的十进制和数字数据类型混淆:在 SQL 中,DAX 十进制数字的对应数据类型是浮点。

货币(Currency)
货币数据类型存储固定的十进制数。它可以表示为 4 位的小数,内部存储为 64 位的整数值除以 10000。在货币数据类型之间执行的所有计算总是忽略 4 位小数点后面的小数。如果需要更精确的数据,则必须进行十进制数据类型的转换。

货币数据类型的默认格式包括货币符号。还可以将货币格式应用于整数和十进制数,还可以使用一种不带货币符号的格式来表示货币数据类型。

文本(String)
DAX 中的每个字符串都存储为 16 位 Unicode 字符串。默认情况下,字符串之间的比较是不区分大小写的,因此这两个字符串“PowerPivot”和“POWERPIVOT”是相等的。

二进制(Binary)
二进制数据类型用于在数据模型中存储图像,在 DAX 中无法访问该数据类型。它主要被 Power View 或其他客户端工具用来显示直接存储在数据模型中的图片。在 Power BI 等其他工具中可能无法使用

空白/Null 类型
BLANK 不对应 SQL 中的 NULL。DAX 中的 BLANK 不遵循 NULL 在 SQL 中的计算逻辑。在中间结果可能是 BLANK 的表达式中,必须注意这种区别。 你可以使用 BLANK 函数创建空白,并使用 ISBLANK 对其进行测试。
关于空白、空字符串和零值的处理:
在这里插入图片描述
DAX 运算符
运算符列表
在这里插入图片描述
注意:IN 运算符 2016 年 11 月发布,可能无法在 Excel 2016 以及更早的版本中使用,详情参考IN 和 CONTAINSROW一文。






OR ( [CountryRegion] = "USA", [Quantity] > 0 ) 

它们分别与下面的写法等价:

[CountryRegion] = "USA" && [Quantity] > 0 [CountryRegion] = "USA" || [Quantity] > 0 

当你必须编写复杂条件时,使用函数代替运算符进行布尔逻辑运算变得非常有用。事实上,当需要格式化大量代码时,函数比运算符更容易格式化和读取。然而,函数的主要缺点是一次只能传入两个参数。如果需要计算两个以上的条件,就需要嵌套函数。

几种基本的报错

现在你已经了解了一些基础语法知识,接下来我们将学习如何优雅的处理无效计算。当引用的数据对公式无效时,无效计算就产生了。例如,你可能执行了一个除以零或将非数值型的列值用于算术运算,如乘法运算的操作。你必须了解这些错误在默认情况下是如何处理的,以及如何采取针对性的操作来截获这些错误。

在学习如何处理错误之前,有必要梳理一下 DAX 公式计算中可能出现的各种错误。它们是:

  1. 转换错误
  2. 算术运算错误
  3. 空值或缺失值

转换错误

第一种错误是转换错误。正如你在本章中看到的,只要运算需要,DAX 就会自动将值在字符串和数字之间转换。下面所有的示例都使用有效的 DAX 表达式:

"10" + 32 = 42 "10" & 32 = "1032" 10 & 32 = "1032" DATE (2010,3,25) = 3/25/2010 DATE (2010,3,25) + 14 = 4/8/2010 DATE (2010,3,25) & 14 = "3/25/" 

这些公式总是正确的,因为它们是用常数值运算的。但是,如果 VatCode 是一个字符串,那么下面的示例结果是什么呢?

SalesOrders[VatCode] + 100 

在本例中,这个求和表达式的第一个运算对象是文本类型,所以你必须确保 DAX 可以将该列中的所有值转换为数字。如果存在部分内容无法被 DAX 转换以满足运算需要,将会导致转换错误。以下是一些典型的情况:

"1 + 1" + 0 = Cannot convert value '1+1' of type string to a number DATEVALUE ("25/14/2010") = Type mismatch 

算术运算错误

第二类错误来自算术运算,例如除以零或负数的平方根。这些都不是与转换相关的错误:当你试图用无效值去调用函数或执行运算时,DAX 都会提示这些错误。

零做除数的情况需要特殊的处理,因为它的行为不是很直观(也许数学家除外)。当你把一个数字除以 0 时,DAX 通常会返回一个无穷大的特殊值(Infinity)。此外,在非常特殊的情况下,0 除以 0 或无穷大除以无穷大,DAX 返回特殊的 NaN(而不是一个数字)。

值得注意的是,Infinity 和 NaN 不是错误,而是 DAX 中的特殊值。事实上,如果你把一个数字除以无穷,这个表达式不会产生错误,但会返回 0:

9954 / ( 7/0 ) = 0

除了这种特殊情况,DAX 在调用带有错误参数的函数时会返回计算错误,比如负数的平方根:

SQRT ( -1 ) = 函数 ‘SQRT’ 的参数的数据类型错误或者结果太大或太小

如果 DAX 检测到这样的错误,它就会阻止表达式的进一步计算,并触发错误。你可以使用 ISERROR 函数检查表达式是否导致错误,这个函数在后面会提到。

空值或缺失值

我们研究的第三类并非特定的错误条件,而是针对计算时存在的空值,当把空值与其他元素结合时,可能会导致意外的结果或计算错误。你需要了解 DAX 是如何处理这些特殊值的。

DAX 用空值(Blank)处理缺失值、空白值或空单元格。空值不是一个真实的值,而是识别这些条件的一种特殊方式。通过调用空值函数可以在 DAX 表达式中获得空值,这与空字符串不同。例如,下面的表达式总是返回一个空白值,它将作为空单元格显示在数据透视表中:

=BLANK() 

就其本身而言,这个表达式是无用的,但是每当你想返回一个空值时,空值函数就变得有用了。例如,你可能想要显示一个空单元格而不是 0,如下面的表达式中计算交易的总折扣,如果折扣为 0,则单元格为空:

= IF ( Sales[DiscountPerc] = 0, BLANK (), Sales[DiscountPerc] * Sales[Amount] ) 

空值本身不是错误类型,它只是显示为空白结果。因此,包含空白的表达式可能返回值或空白,这取决于计算的需要。例如,当 Sales[Amount]为空时,下面的表达式返回空:

= 10 * Sales[Amount] 

换句话说,当有一项或两项为空时,乘积的结果为空。在 DAX 表达式中,这种空值的传递也发生在其他一些算术和逻辑运算中,如下面的例子所示:

BLANK () + BLANK () = BLANK () 10 * BLANK () = BLANK () BLANK () / 3 = BLANK () BLANK () / BLANK () = BLANK () BLANK () || BLANK () = FALSE BLANK () && BLANK () = FALSE BLANK () = BLANK () = TRUE 

然而,空值的传递并不适用于所有公式。有些计算并不传递空值,而是根据公式的其他项返回值。这些示例包括加法、减法、空值作为除数,以及空值与有效值之间的逻辑操作。在下列表达式中,你可以看到关于这些条件的例子,以及它们的结果:

BLANK () - 10 = -10 18 + BLANK () = 18 4 / BLANK () = 无穷大 0 / BLANK () = NaN FALSE || BLANK () = FALSE FALSE && BLANK () = FALSE TRUE || BLANK () = TRUE TRUE && BLANK () = FALSE 

Excel 和 SQL 中的空值

Excel 使用不同的方法处理空值。在 Excel 中,当在求和或乘法中使用空值时,它们都被认为是 0,但如果它们是除法或逻辑表达式的一部分,则会返回错误。

在 SQL 中,NULL 值以不同于 DAX 中的空值的方式在表达式中传递。正如你在前面的示例中看到的,DAX 表达式中出现的空白并不总是导致空白结果,而 SQL 中出现的 NULL 通常使得整个表达式求值为 NULL。

理解空值或缺失值在 DAX 表达式中的行为,并在计算中使用空值函数返回空单元格,是控制 DAX 表达式结果的重要技能。当你检测到错误的结果或其他错误类型时,可以利用空值函数来处理,你将在下一节中学习到这一点。

拦截错误

现在你已经看到了各种可能发生的错误,接下来我们将学习截获和纠正错误的方法,以及如何显示有用的错误提示消息。DAX 表达式的错误通常取决于表达式本身引用的表和列中的值。因此,你可能希望避免这些错误出现并返回出错消息。标准做法是检查表达式是否返回错误,如果返回,则用一条消息或默认值替换错误,在这方面 DAX 提供了专门的函数。

第一个是 IFERROR 函数,它与 IF 函数非常相似,但它计算的不是布尔条件,而是检查表达式是否返回错误。你可以在下面看到 IFERRROR 函数的两个典型用法:

= IFERROR ( Sales[Quantity] * Sales[Price], BLANK () ) = IFERROR ( SQRT ( Test[Omega] ), BLANK () ) 

在第一个表达式中,如果 Sales[Quantity]或 Sales[Price]是不能转换为数字的字符串格式,则返回的表达式为空值;否则,返回数量和价格的乘积。

在第二个表达式中,每当 Test[Omega]列包含负数时,结果都是空单元格。

当你以这种方式使用 IFERROR 时,你会遵循一种更一般的模式,即使用 ISERRORIF

= IF ( ISERROR ( Sales[Quantity] * Sales[Price] ), BLANK (), Sales[Quantity] * Sales[Price] ) = IF ( ISERROR ( SQRT ( Test[Omega] ) ), BLANK (), SQRT ( Test[Omega] ) ) 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/137000.html

(0)
上一篇 2025-06-23 18:33
下一篇 2025-06-23 19:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信