从数据到信息
从信息到洞察

数据类型和运算符

数据类型

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

  • 整数 (Integer)
  • 十进制数 (Float)
  • 货币 (Currency), 内部存储为整数的固定小数
  • 日期 (DateTime)
  • 布尔值 (TRUE/FALSE)
  • 文本 (String)
  • 二进制 (Binary)
  • Blank/Null 类型
  • 变体(Variant) 类型

DAX 数据类型在不同工具中使用的名称

DAX 有一个强大的类型处理系统,因此你不必担心数据类型:当你编写 DAX 表达式时,结果的类型基于表达式使用的术语类型自动调整。我们称之为隐式转换,但在某些情况下,它不会进行转换。 例如,如果 DAX 函数需要日期数据类型,而你的列的数据类型为文本,DAX 函数将不能正常工作。 因此,获取适用于列的正确数据类型是重要并且有用的,如果 DAX 表达式返回的类型不是预期的类型,你需要须检查表达式使用的术语的数据类型。

例如,如果某列的数据类型是日期,那么求和的结果也是日期;然而,如果对整数使用相同的运算符,则结果是整数。这就是运算符重载,你可以在下图中看到它的行为示例,其中 OrderDatePlusOneWeek 列是通过在 Order Date 列的值上增加 7 来计算的。结果,就像我们说的,是一个日期。

向日期列添加一个整数会导致日期增加相应的天数

除了运算符重载之外,在需要时 DAX 还会自动将字符串转换为数字,或者将数字转换为字符串。例如,如果使用连接字符串的&运算符,DAX 将把它的参数转换成字符串。例如:

= 5 & 4

将返回字符串形式的“54”,另一公式

= "5" + "4"

返回数值型结果 9

结果值依赖于运算符,而不是引用的列,列根据运算符的要求进行转换。即使这种行为看起来很方便,稍后你将看到在这些自动转换期间可能发生哪些错误。我们建议避免自动转换。如果需要进行某种转换,那么最好主动介入并使用显示转换。比如上面的例子应该使用:

= VALUE ( "5" ) + VALUE ( "4" )

熟悉 Excel 或其他语言的人可能更熟悉 DAX 数据类型。你可以在这里找到关于 DAX 数据类型的规范。然而,对于每一种数据类型介绍一些注意事项是很有必要的。

整数 (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) 的正数或负数。 在需要控制舍入的情况下,整数类型非常有用。

Power BI Desktop 数据模型支持 64 位整数值,但由于存在 JavaScript 限制,因此视觉对象可安全表达的最大数字是 9,007,199,254,740,991 (2^53-1)。 如果在数据模型中使用大于以上值的数字,可在将该数字添加到视觉对象前,通过计算减小其大小

十进制数(Float)

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

货币(Currency)

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

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

当表达式包含不同数据类型之间的乘法和除法时,需要关注是否涉及货币数据类型。因为在计算中进行类型转换的位置不同可能会产生不同的结果。货币数据类型对于避免聚合中的某些舍入错误非常重要,但是应该谨慎地管理它,以避免复杂表达式产生意外的舍入错误。

日期/时间(Datetime)

DAX 在日期/时间数据类型中存储日期。这种格式内部使用浮点数,其中整数对应于 1899 年 12 月 30 日以来的天数,而小数部分则表示当天的份数。小时、分钟和秒被转换成一天的小数部分。因此,下面的表达式返回当前日期加上一天(正好是 24 小时):

= NOW()+1

它的结果是在计算当前时间的明天的日期,如果你只需要使用日期/时间的日期部分,可以使用 TRUNC 函数来删除小数部分。

Power BI 还提供另外两种数据类型:日期类型和时间类型。在引擎内部,它们是日期/时间的简单变体。实际上,两种类型分别只存储日期/时间的整数部分或小数部分。

闰年错误

1983 年发布的流行电子表格程序 Lotus 1-2-3 在处理 DateTime 数据类型时出现了一个错误。它认为 1900 年是闰年,尽管事实并非如此(一个世纪的最后一年是闰年,前提是前两位数字除以 4 没有余数)。当时,Excel 第一版的开发团队故意复制了这个 bug,以保持与 Lotus 1-2-3 的兼容性。从那以后,出于兼容性考虑,Excel 的每一个新版本都把这个 bug 作为一个特性来维护。

为了保持与 Excel 的向后兼容,目前这个 bug 仍然在 DAX 中。Bug 的存在(或者我们应该称之为特性吗?)可能会导致 1900 年 3 月 1 日之前出现错误。因此,根据设计,DAX 的第一个官方支持的日期是 1900 年 3 月 1 日。在此日期之前执行的日期计算可能会导致错误,应该被认为是不准确的。

DAX 中的 1 代表 1899 年 12 月 31 日,而 EXCEL 是 1900 年 1 月 1 日,存在这种差别的原因是 Lotus 1-2-3 的最初版本有一个 bug,认为 1900 是一个闰年,其中包括 1900 年 2 月 29 日。实际上 1900 年不是闰年,所以在 1900 年 3 月 2 日之前的日期在 Lotus 1-2-3 中被误写了。由于莲花的电子表格在当时非常受欢迎,为了与其竞争,微软在自家的 EXCEL 上继承了这个 bug 以便用户可以无缝切换。DAX 的开发者对这个 Bug 采用了另一种不同的实现方式,导致在这个特定的时间段内,DAX 与 Excel 存在 1 天的差距。

如果你需要在 1900 年之前进行计算,你应该使用数学方法来将其移动到 1900 年之后的日期,执行计算,然后再平移回去。

布尔值(TRUE/FALSE)

布尔数据类型用于表示逻辑条件。例如,由以下表达式定义的计算列类型为布尔型:

= Sales[Unit Price] > Sales[Unit Cost]

你也可以将布尔数据类型视为数字,其中 TRUE=1 和 FALSE=0。这在排序时很有用,因为 TRUE >FALSE。相反的,如果在逻辑判断中直接使用数字,那么 0 将会被视为 FALSE,例如下面的表达式始终返回空

FILTER(Table,0)

文本(String)

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

PowerQuery 比较字符串时默认区分大小写,这是两者的一个不同点,需特别留意。如果你使用的是 Analysis Services 表格模型,可以自行设置是否区分大小写

二进制(Binary)

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

在圣经第一版中此处使用的格式类型是二进制大对象(BLOB)

空白/Null 类型

BLANK 不对应 SQL 中的 NULL。DAX 中的 BLANK 不遵循 NULL 在 SQL 中的计算逻辑。在中间结果可能是 BLANK 的表达式中,必须注意这种区别。 你可以使用 BLANK 函数创建空白,并使用 ISBLANK 对其进行测试。

关于空白、空字符串和零值的处理:

表达式 DAX Excel
BLANK + BLANK BLANK 0(零)
BLANK + 5 5 5
BLANK * 5 BLANK 0(零)
5/BLANK 无穷大 错误
0/BLANK NaN 错误
空白/空白 BLANK 错误
FALSE OR BLANK FALSE FALSE
FALSE AND BLANK FALSE FALSE
TRUE OR BLANK TRUE TRUE
TRUE AND BLANK FALSE TRUE
BLANK OR BLANK BLANK 错误
BLANK AND BLANK BLANK 错误

关于 BLANK 的更多注意事项,请在阅读BLANK 的函数介绍

变体/Variant 类型

变体数据类型用于可能返回不同数据类型的度量值,具体取决于度量值使用的条件表达式。例如,下面的语句可以返回整数或字符串,所以它返回一个变体类型:

IF ( [measure] > 0, 1, "N/A" )
计算列不能返回变体类型,否则会收到提示:“不能使用生成变量数据类型的表达式定义计算列”。变体适用于 DAX 度量值,或更一般的说,DAX 表达式

 

DAX 运算符

了解了运算符在确定表达式类型的重要性之后,我们通过下表来看一下 DAX 中的运算符列表。

运算符列表

参数类型 符号 用法 举例
小括号 ( ) 改变计算优先级和分组 (5+2)*3
四则运算 + 相加 4 + 2
相减/逻辑否 5 − 3
* 相乘 4 * 2
/ 相除 4 / 2
比较符号 = 等于 [CountryRegion] = “USA”
<> 不等于 [CountryRegion] <> “USA”
> 大于 [Quantity] > 0
>= 大于或等于 [Quantity] >= 100
< 小于 [Quantity] < 0
<= 小于或等于 [Quantity] <= 100
== 严格相等 Product[Color] == BLANK()
文本连接 & 连接符 “Value is” & [Amount]
逻辑判断 && 两个布尔表达式之间的逻辑“与” [CountryRegion] = “USA” && [Quantity]>0
|| 两个布尔表达式之间的逻辑“或” [CountryRegion] = “USA” || [Quantity] > 0
IN 元素包含在列表中 [CountryRegion] IN {“USA”, “Canada”}
NOT 否定判断 NOT [Quantity] > 0

注意:IN 运算符 2016 年 11 月发布,可能无法在 Excel 2016 以及更早的版本中使用,详情参考IN 和 CONTAINSROW一文。

此外,逻辑运算符也可以作为 DAX 函数使用,语法非常类似于 Excel。例如,你可以这样写:

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

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

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

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

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

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

严格相等运算

本文隐藏内容查看价格为1G币,请先
单独购买的内容长期有效,不受时间限制(购买前先刷新当前页面)。加入VIP会员可享受全站权益,性价比更高。

 

扩展阅读:

Power BI 中的数据类型

理解 DAX 中的数值类型转换

 

13
说点什么

1000
 
鼓掌微笑开心憧憬爱你色并不觉得吃瓜doge二哈喵喵思考笑哭捂脸悲伤大哭抓狂汗偷笑打脸捂眼黑线问号晕拜拜闭嘴衰咒骂ok作揖
6 评论数
7 被回复的评论
6 订阅评论的人数
 
查看最近回复
查看最热评论
  订阅本文评论  
最新 最旧 得票最多
提醒
成员
jb870610

高老师,计算列不也是DAX表达式吗?

1.png
成员
jb870610

高老师,文中提到的隐式转换和运算符重载不是一回事,是隐式转换包含运算符重载这种情况吗?

1.png
成员
YY_bogy

想请教老师,空字符串,blank,””,要怎么区分呢?

成员
teddy_19_ajie

想请教老师:在日期类型那部分内容里提到的1900年3月1日的问题,具体可能会发生什么样错误?在使用DATE函数的时候,是可以返回类似1899年1月1日这样的日期的,那么前面提到的错误,会是在什么情况下发生的呢?谢谢。

成员
hhcx

严格相等这个很有帮助,我遇到过需要区分0和blank的情况,在网上找了答案,没有提到严格相等的。最后使用isblank来解决的。

成员
龙雄

高飞老师,我补充一下测试的结果 “在货币数据类型之间执行的所有计算总是忽略4位小数点后面的小数”
实际测试的结果是 小数点4位以后的小数,忽略的方式是四舍五入。

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数