第2章 DAX简介
2.1 理解DAX计算
2.2了解计算列和度量值
2.3 变量入门
2.4 DAX表达式中的错误处理
2.5 格式化DAX代码
2.6 聚合函数和迭代函数
2.7 使用常见的DAX函数
在本章中,我们开始讨论DAX语言。在这里,您将学习该语言的语法,计算列与度量值之间的差异(在某些旧的Excel版本中也称为计算字段)以及DAX中最常用的函数。
因为这是介绍性的一章,所以它没有深入介绍许多功能。后面的章节中将更详细地讲解。现在了解功能并开始着眼于DAX语言就够了。当我们在Power BI,Power Pivot或Analysis Services中涉及数据模型的功能时,即使产品中没有该功能,我们也会使用术语Tabular(表格模型)。例如,"Tabular in DirectQuery"是指Power BI和Analysis Services中可用的DirectQuery模式但Excel中没有。
理解DAX计算
在研究更复杂的公式之前,需要学习DAX的基础知识,包括DAX语法、DAX可以处理的不同数据类型、基本运算符以及如何引用列和表,接下来的几节中将讨论这些概念。
我们使用DAX计算表中的列值,聚合、计算和搜索数据,所有计算最终都涉及表和列。因此首先要学习的语法是如何引用表中的列。
引用列的通用格式是将表名写在单引号中,然后将列名写在方括号中,如下所示:
Sales'[Quantity]
如果表名不以数字开头、不包含空格并且不是保留字(例如Date或Sum),则可以省略单引号。
如果在某个表中定义公式时引用该表中的列或度量值,则表名也省略。因此,[Quantity]如果写在Sales表中的计算列或度量值中是有效的列引用。尽管如此,但我们强烈建议您不要省略表名。对此我们现在不去解释它的意义所在,当您阅读第5章 " 了解CALCULATE 和CALCULATETABLE " 时,原因就显而易见。 当您阅读DAX代码时,能够区分度量值(稍后讨论)和列至关重要。实际标准是始终在列引用中使用表名,而在度量值引用中避免使用表名。您越早采用此标准,DAX用起来就越轻松。因此,应该尽快习惯这种引用列和度量值的方式:
Sales[Quantity] * 2 --这是一个列引用
[Sales Amount] * 2 --这是一个度量值引用
DAX中的注释
上次代码示例中首次出现了DAX中的注释。DAX支持单行注释和多行注释。单行注释以-或//开头,紧接着的该行的其余内容被视为注释。= Sales[Quantity] * Sales[Net Price] -- Single-line comment = Sales[Quantity] * Sales[Unit Cost] // Another example of single-line comment
最好避免在DAX度量值、计算列或计算表的表达式末尾添加注释。这些注释起初可能不可见,并且DAX 格式化器等工具可能不支持,本章稍后将对此进行讨论。
在学习了上下文转换(第5章)后,您将了解该标准的基本原理。现在,请相信我们并遵守该标准。
DAX数据类型
DAX可以处理七个不同的数字类型,随着时间的流逝,Microsoft在不同时期为相同的数据类型引入了不同的名称,造成了混乱。
表2-1中可以找到DAX各种数据类型的不同名称。
本书中,秉承数据库和商业智能社区事实上的标准,我们使用表格2- 1第一列中的名称。例如,在Power BI中,包含TRUE或FALSE的列将称为TRUE / FALSE,而在SQL Server中,将其称为BIT。但是,这种类型的值的历史上最常用的名称是Boolean。
表2-1 数据类型
DAX | POWER BI | Power Pivot和Analysis Services | 对应的常规数据类型(如SQL Server) | 表格对象模型(TOM) |
---|---|---|---|---|
Integer | Whole Number | Whole Number | Integer/INT | Int64 |
Decimal | Decimal Number | Decimal Number | Floating point/DOUBLE | double |
Currency | Fixed Decimal Number | Currency | Currency/MONNEY | Decimai |
DateTime | DateTime, Date,Time | Date | Date/DATETIME | dateTime |
Bolean | True/False | True/False | Boolean/BTT/ | boolean |
String | Text | Text | String/NVARCHAR (MAX) | string |
Variant | variant | |||
Binary | Binary | Binary | Blob/VARBINARY (MAX) | binary |
DAX具有强大的类型处理系统,因此我们不必担心数据类型。在DAX表达式中,计算结果数据类型取决于表达式中使用的术语。如果从DAX表达式返回的数据类型不是预期的数据类型,则必须注意,调查表达式本身中使用的术语将导致的数据类型。
例如,如果求和数据中的一项是日期,则结果也是日期;同理,如果对整数求和,则结果为整数。此行为称为运算符重载,图2-1中显示了一个示例,其中OrderDatePlusOneWeek列Order Date列的值上加7,计算结果是一个日期。
Sales[OrderDatePlusOneWeek] = Sales[Order Date] + 7
除了运算符重载之外,DAX还会在运算符需要时,自动将字符串转换为数字,将数字转换为字符串。例如,如果我们使用"&"运算符来连接字符串,则DAX会将其参数转换为字符串。
以下公式以字符串形式返回" 54":
= 5&4
然而下一公式返回结果为整数9:
= "5" + "4"
计算结果值取决于运算符,而不取决于源列,源列将根据运算符的要求进行转换。尽管此行为貌似很方便,但在本章后面的内容中,您会看到在这些自动转换过程中可能发生的错误。此外,并非所有操作符都遵循此行为。例如,比较运算符不能将字符串与数字进行比较。因此,您可以将一个数字与字符串相加,但是不能将数字与字符串进行比较。你可以在这里找到一个完整的参考:
https://docs.microsoft.com/en-us/power-BI/desktop-data-types
https://docs.microsoft.com/en-us/power-bi/desktop-data-types
由于规则是如此复杂,因此建议您完全避免自动转换。如果需要进行转换,建议您控制它并使转换明确。为了更明确,前面的示例应如下所示:
= VALUE(" 5")+ VALUE(" 4")
习惯使用Excel或其他语言的人可能熟悉DAX数据类型。对数据类型的详细规定取决于引擎,并且对于Power BI,Power Pivot或Analysis Services,它们可能有所不同。您可以在以下网址找到有关Analysis Services DAX数据类型的更多详细信息:有关数据类型的注意事项非常有用。
http://msdn.microsoft.com/en-us/library/gg492146.aspx
在以下网址找到Power BI信息:
https://docs.microsoft.com/zh-cn/power-bi/desktop-data-types
Integer
DAX仅具有一种Integer数据类型(整数)可以存储64位值。DAX中整数值之间的所有内部计算也使用64位值。
Decimal
Decimal(十进制数)总是存储为双精度浮点值。请勿将此DAX数据类型与Transact-SQL的decimal and numeric数据类型混淆。SQL中DAX 的Decimal对应数据类型为Float。
Currency
Currency(货币)数据类型存储固定十进制数,在Power BI中也被称为Fixed Decimal Number(固定十进制数)。它可以代表四位小数,内部存储为64位整数值除以10,000。对Currency数据类型进行加减法运算会忽略小数点后第四位的小数,而乘除法则产生一个浮点值,从而提高了计算结果的精度。通常,如果需要提供高于四位数的精度,则必须使用Decimal数据类型。
Currency数据类型的默认格式包括货币符号。我们还可以将货币格式应用于整数和十进制数,并且可以对Currency数据类型使用不带货币符号的格式。
DateTime
DAX将日期存储为DateTime类型。此格式在内部使用浮点数,其中整数部分对应于1899年12月30日以来的天数,多出的小时、分钟和秒转换为小数部分。因此,以下表达式返回当前日期加上一天(恰好是24小时):
= TODAY()+ 1
计算结果是明天的日期。如果只需要使用DateTime的日期部分,请记住使用TRUNC除去小数部分。
Power BI提供了另外两种数据类型:Date和Time。在内部,它们是DateTime的简单变体。实际上,Date和Time分别存储DateTime的整数或小数部分。
Boolean
Boolean数据类型(布尔)用于表示逻辑条件。例如,以下表达式定义的计算列为布尔型:
= Sales[Unit Price] > Sales[Unit Cost]
您还会看到布尔型为数字,其中TRUE等于1,而FALSE等于0。由于TRUE > FALSE,这种表示法被证明有时对排序有利。
DAX中的每个字符串都存储为Unicode字符串,其中每个字符都以16位存储。默认情况下,字符串之间的比较不区分大小写,因此两个字符串" Power BI"和" POWER BI"被视为相等。
Variant
Variant数据类型(变体)用于根据不同的条件,返回不同的数据类型。例如,以下语句既可能返回整数又可能返回字符串,因此设置为变体类型:
IF([measure]> 0,1,"N/A")
变体数据类型不能用于常规表中列的数据类型。通常DAX度量值表达式可以是Variant。
Binary
Binary(二进制)数据类型在数据模型中用来存储图像或其它非结构化信息使用。它在DAX中不可用。主要是Power View使用它,在Power BI等其他工具中可能不可用。
DAX运算符
既然您已经了解了运算符在确定表达式类型中的重要性,现在来看表2-2列出的DAX中可用的运算符。
表2-2 运算符
运算符类型 | 符号 | 使用 | 示例 |
---|---|---|---|
括号 | () | 优先顺序和参数分组 | (5+2)*3 |
算术 | + | 加 | 4+2 |
算术 | - | 减/负 | 5-3 |
算术 | * | 乘 | 4*2 |
算术 | / | 除 | 4/2 |
比较 | = | 等于 | [CountryRegion] = “USA” |
比较 | <> | 不等于 | [CountryRegion] <>“USA” |
比较 | > | 大于 | [Quantity] > 0 |
比较 | >= | 大于等于 | [Quantity] >= 100 |
比较 | < | 小于 | [Quantity] < 0 |
比较 | <= | 小于等于 | [Quantity] <= 100 |
文本 | & | 字符串连接 | “Value is” & [Amount] |
逻辑 | && | 逻辑与 | [CountryRegion] = “USA” |
逻辑 | 逻辑或 | [CountryRegion] = “USA” | |
逻辑 | IN | 列表中是否包含元素 | [CountryRegion] IN {“USA”, “Canada”} |
逻辑 | NOT | 逻辑非 | NOT [Quantity] > 0 |
此外,逻辑运算符还可用作DAX函数,其语法类似于Excel的语法。例如,我们可以编写如下表达式:
AND ( [CountryRegion] = "USA", [Quantity] > 0 )
OR ( [CountryRegion] = "USA", [Quantity] > 0 )
这些示例分别等效于以下内容:
[CountryRegion] ="USA" && uantity] > 0
[CountryRegion] ="美国" || [Quantity] > 0
在编写复杂条件时,使用函数而不是运算符进行布尔逻辑运算将是很有帮助的。实际上,在格式化大段代码时,格式化和可读性函数比操作符容易得多。
但是,函数的主要缺点是我们一次只能传递两个参数。因此,如果要评估的条件超过两个,则必须嵌套函数。
表构造函数
在DAX中,我们可以直接在代码中定义匿名表。如果表只有一列,则语法仅需要一列值(每行一个),并用花括号括起来。我们可以用括号来分隔多行,如果表是由一列组成的话,括号可以用也可以不用。例如,以下两个定义是等效的:
{"Red","Blue","White"}
{("Red" ),("Blue"),("White")}
如果表有多个列,每行的数据则必须使用括号。每列的所有行应具有相同的数据类型;否则,DAX将自动将列转换数据类型至可以容纳整列各行所有数据类型。
{
( "A", 10, 1.5, DATE ( 2017, 1, 1 ), CURRENCY ( 199.99 ), TRUE ),
( "B", 20, 2.5, DATE ( 2017, 1, 2 ), CURRENCY ( 249.99 ), FALSE ),
( "C", 30, 3.5, DATE ( 2017, 1, 3 ), CURRENCY ( 299.99 ), FALSE )
}
表构造函数通常与IN运算符一起使用。例如,以下是DAX表述中的有效语法:
'Product'[Color] IN { "Red", "Blue", "White" }
( 'Date'[Year], 'Date'[MonthNumber] ) IN { ( 2017, 12 ), ( 2018, 1 ) }
第二个示例显示使用IN运算符比较一组列(元组)的语法。这样的语法不能与比较运算符一起使用。换句话说,以下语法无效:
( 'Date'[Year], 'Date'[MonthNumber] ) = ( 2007, 12 )
但是,我们可以使用单行表构造函数和IN运算符重写,如下所示:
( 'Date'[Year], 'Date'[MonthNumber] ) IN { ( 2007, 12 ) }
条件语句
在DAX中,我们可以使用IF函数编写条件表达式。例如,我们可以写一个依据数量值是否大于1分别返回MULTI或SINGLE的表达式。
IF (
Sales[Quantity] > 1,
"MULTI",
"SINGLE"
)
该IF函数有三个参数,但只有前两个是必选的。第三个是可选的,默认为BLANK。参见以下代码:
IF (
Sales[Quantity] > 1,
Sales[Quantity]
)
它对应于以下显式版本:
IF (
Sales[Quantity] > 1,
Sales[Quantity],
BLANK ()
)
网友评论