DirectQuery 模式下的 DAX 公式兼容性 (SSAS 2014)

数据分析表达式语言(DAX)可用于创建度量值和其他自定义公式,以便在 Analysis Services 表格模型、Excel 工作簿中的 PowerPivot 数据模型和 Power BI Desktop 数据模型中使用。 在大多数情况下,在这些环境中创建的模型是相同的,可以使用相同的度量值、关系和 KPI 等。但是,如果你创作 Analysis Services 表格模型并将其部署在 DirectQuery 模式下,则可以对公式有一些限制。 本主题概述了这些差异,列出了兼容级别 1100 或 1103 和 DirectQuery 模式下 SQL Server 2014 Analysis Services 表格模型不支持的函数,并列出了支持但可能返回不同结果的函数。

在本主题中,我们使用 术语内存中模型 来引用表格模型,该模型完全托管在以表格模式运行的 Analysis Services 服务器上的内存中缓存数据。 我们使用 DirectQuery 模型 来引用已在 DirectQuery 模式下创作和/或部署的表格模型。 有关 DirectQuery 模式的信息,请参阅 DirectQuery 模式(SSAS 表格)。

内存中和 DirectQuery 模式之间的差异

在 DirectQuery 模式下部署的模型的查询可以返回与内存中模式下部署的相同模型不同的结果。 这是因为使用 DirectQuery,数据直接从关系数据存储查询,公式所需的聚合是使用相关关系引擎执行的,而不是使用 xVelocity 内存中分析引擎(VertiPaq)进行存储和计算。

例如,某些关系数据存储处理数值、日期、null 等的方式存在差异。

相比之下,DAX 语言旨在尽可能模拟Microsoft Excel 中函数的行为。 例如,处理 null、空字符串和零值时,Excel 会尝试提供最佳答案,而不考虑精确的数据类型,因此 xVelocity 引擎执行相同的作。 但是,在 DirectQuery 模式下部署表格模型并将公式传递给关系数据源进行评估时,必须根据关系数据源的语义处理数据,这通常需要对空字符串和 null 进行不同的处理。 因此,当根据缓存的数据和仅从关系存储返回的数据进行评估时,同一公式可能会返回不同的结果。

此外,某些函数根本不在 DirectQuery 模式下使用,因为计算需要将当前上下文中的数据作为参数发送到关系数据源。 例如,PowerPivot 工作簿中的度量值通常使用引用工作簿中可用的日期范围的时间智能函数。 此类公式通常不能在 DirectQuery 模式下使用。

语义差异

本部分列出了可以期望的语义差异类型,并描述了可能适用于函数使用或查询结果的任何限制。

比较

内存中模型中的 DAX 支持两个表达式的比较,这些表达式解析为不同数据类型的标量值。 但是,在 DirectQuery 模式下部署的模型使用关系引擎的数据类型和比较运算符,因此可能会返回不同的结果。

在 DirectQuery 数据源的计算中使用时,以下比较将始终返回错误:

  • 与任何字符串数据类型相比的数字数据类型

  • 与布尔值进行比较的数字数据类型

  • 与布尔值进行比较的任何字符串数据类型

通常,DAX 对内存模型中的数据类型不匹配更宽容,并将最多尝试两次隐式转换值,如本部分所述。 但是,发送到 DirectQuery 模式下的关系数据存储的公式会被更严格地评估,遵循关系引擎的规则,因此更有可能失败。

字符串和数字的比较
例: "2" < 3

公式将文本字符串与数字进行比较。 在 DirectQuery 模式和内存中模型中,表达式为 true

在内存模型中,结果 为 true ,因为字符串中的数字隐式转换为数值数据类型,用于与其他数字进行比较。 SQL 还隐式将文本数字强制转换为数字,以便与数字数据类型进行比较。

请注意,这表明与 PowerPivot 的第一个版本相比,行为发生了变化,会返回 false,因为在这种情况下,文本“2”始终被视为大于任何数字。

文本与布尔值的比较
例: "VERDADERO" = TRUE

此表达式将文本字符串与布尔值进行比较。 通常,对于 DirectQuery 或 In-Memory 模型,将字符串值与布尔值进行比较会导致错误。 规则的唯一例外是字符串包含 true 或单词 false;如果字符串包含任何 true 或 false 值,则进行到布尔值的转换,并进行比较以给出逻辑结果。

空值比较
例: EVALUATE ROW("X", BLANK() = BLANK())

此公式将 NULL 的 SQL 等效项与 null 进行比较。 它在内存中和 DirectQuery 模型中返回 true ;在 DirectQuery 模型中进行预配,以确保与内存中模型类似的行为。

请注意,在 Transact-SQL 中,null 永远不会等于 null。 但是,在 DAX 中,空白等于另一个空白。 对于所有内存中模型,此行为相同。 请务必注意,DirectQuery 模式使用 SQL Server 的大部分语义;但是,在这种情况下,它与它分离,为 NULL 比较提供了新的行为。

转换

DAX 中没有强制转换函数,但隐式转换在许多比较和算术运算中执行。 它是确定结果数据类型的比较或算术运算。 例如,

  • 布尔值在算术运算中(如 TRUE + 1)被视为数值,或函数 MIN 应用于布尔值的列。 NOT运算也会返回一个数值。

  • 在比较中,布尔值始终被视为逻辑值,在与 EXACT、AND、OR、> 或 ||一起使用时。

从字符串转换为布尔值
在内存模型和 DirectQuery 模型中,仅允许这些字符串进行到布尔值的强制转换:“”(空字符串)、“true”“false”;其中,空字符串会转换为 false 值。

将任何其他字符串转换为布尔数据类型会导致错误。

从字符串转换为日期/时间
在 DirectQuery 模式下,从日期和时间的字符串表示形式转换为实际 日期/ 时间值的行为方式与在 SQL Server 中的行为相同。

有关指导 PowerPivot 模型中字符串转换为 日期时间 数据类型的规则的信息,请参阅 DAX 语法参考

使用内存中数据存储的模型支持日期的文本格式范围比 SQL Server 支持的日期的字符串格式更有限。 但是,DAX 支持自定义日期和时间格式。

从字符串转换为其他非布尔值
从字符串转换为非布尔值时,DirectQuery 模式的行为与 SQL Server 相同。 有关详细信息,请参阅 CAST 和 CONVERT (Transact-SQL)

不允许从数字转换为字符串
例: CONCATENATE(102,",345")

SQL Server 中不允许从数字转换为字符串。

此公式在表格模型和 DirectQuery 模式下返回错误;但是,公式在 PowerPivot 中生成结果。

DirectQuery 不支持两次尝试的类型转换
内存模型通常在第一次尝试失败时会再次尝试。 这永远不会在 DirectQuery 模式下发生。

例: TODAY() + "13:14:15"

在此表达式中,第一个参数具有 datetime 类型,第二个参数具有类型 字符串。 但是,组合作数时转换的方式不同。 DAX 将执行从 字符串双精度浮点数 的隐式转换。 在内存模型中,公式引擎尝试直接转换为 double,如果失败,它将尝试将字符串转换为 日期时间

在 DirectQuery 模式下,仅应用从 字符串double 的直接强制转换。 如果此强制转换失败,公式将返回错误。

数学函数和算术运算

某些数学函数将在 DirectQuery 模式下返回不同的结果,因为基础数据类型或可在操作中应用的类型转换存在差异。 此外,上述对允许值范围的限制可能会影响算术运算的结果。

添加顺序
创建一个添加一系列数字的公式时,内存中模型可能会按与 DirectQuery 模型不同的顺序处理这些数字。 因此,当您有许多非常大的正数和非常大的负数时,可能会在一个操作中出现错误,并且会影响另一个操作的结果。

使用 POWER 函数
例: POWER(-64, 1/3)

在 DirectQuery 模式下,当将负值提升为小数指数时,POWER 函数不能使用负值作为基值。 这是 SQL Server 中预期的行为。

在内存中模型中,公式返回 -4。

数值溢出操作
在 Transact-SQL 中,导致数值溢出的作返回溢出错误;因此,导致溢出的公式也会在 DirectQuery 模式下引发错误。

但是,内存中模型中使用的相同公式返回八字节整数。 这是因为公式引擎不进行数值溢出的检查。

包含空白的 LOG 函数返回不同的结果
SQL Server 处理与 xVelocity 引擎不同的 null 和空白。 因此,以下公式在 DirectQuery 模式下返回错误,但在内存中模式下返回无穷大(-inf)。

EXAMPLE: LOG(blank())

相同的限制适用于其他对数函数:LOG10 和 LN。

有关 DAX 中 空白 数据类型的详细信息,请参阅 DAX 语法参考

除以 0 和除以空
在 DirectQuery 模式下,除以零(0)或除以 BLANK 始终会导致错误。 SQL Server 不支持无穷大的概念,因为任何以0为除数的除法的自然结果是无穷大,因此会产生错误。 但是,SQL Server 支持除以 null,结果必须始终等于 null。

与其返回不同的结果,在 DirectQuery 模式下,这两种类型的操作(除以零和除以 null)都返回错误。

请注意,在 Excel 和 PowerPivot 模型中,除以零也返回错误。 除以空白将返回一个空白。

以下表达式在内存中模型中都是有效的,但在 DirectQuery 模式下将失败:

1/BLANK

1/0

0.0/BLANK

0/0

BLANK/BLANK表达式是一种特殊情况,在内存中模型和 DirectQuery 模式下返回BLANK

支持的数值和日期时间范围

PowerPivot 和内存中表格模型中的公式受到与 Excel 相同的限制,即实际数字和日期允许的最大值。 当从计算或查询中返回最大值,或在对值进行转换、强制转换、舍入或截断时,可能会出现差异。

  • 如果 CurrencyReal 类型的值相乘,并且结果大于最大可能值,则 DirectQuery 模式下不引发错误,并返回 null。

  • 在内存中模型中,不会引发错误,但返回最大值。

通常,由于 Excel 和 SQL Server 接受的日期范围不同,因此仅当日期在公共日期范围内(包括以下日期)内时,才能保证结果匹配:

  • 最早日期:1990 年 3 月 1 日

  • 最新日期:9999 年 12 月 31 日

如果公式中使用的任何日期都超出此范围,则公式将导致错误,或者结果不匹配。

CEILING 支持的浮点值
例: EVALUATE ROW("x", CEILING(-4.398488E+30, 1))

DAX CEILING 函数的 Transact-SQL 等效版本只支持数值大小为 10^19 或更小的值。 经验法则是浮点值应该能够适合大整数 bigint

日期部分函数,其日期范围不足
仅当用作参数的日期位于有效日期范围内时,才保证 DirectQuery 模式下的结果与内存中模型中的结果匹配。 如果未满足这些条件,将引发错误,否则公式将在 DirectQuery 中返回与内存中模式不同的结果。

示例: MONTH(0)YEAR(0)

在 DirectQuery 模式下,表达式分别返回 12 和 1899。

在内存中模型中,表达式分别返回 1 和 1900。

例: EOMONTH(0.0001, 1)

仅当作为参数提供的数据在有效日期范围内时,此表达式的结果才会匹配。

示例: EOMONTH(blank(), blank())EDATE(blank(), blank())

此表达式的结果在 DirectQuery 模式和内存中模式中应相同。

截断时间值
例: SECOND(1231.04097222222)

在 DirectQuery 模式下,根据 SQL Server 的规则截断结果,表达式的计算结果为 59。

在内存模型中,每个中间运算的结果会被舍入;因此,表达式的计算结果为 0。

以下示例演示如何计算此值:

  1. 输入(0.04097222222)的分数乘以 24。

  2. 生成的小时值 (0.983333333328) 乘以 60。

  3. 生成的分钟值为 58.99999999968。

  4. 分钟值(0.999999999968)的分数乘以 60。

  5. 生成的第二个值(59.9999999808)向上舍入为 60。

  6. 60 等效于 0。

不支持 SQL 时间数据类型
内存中模型不支持使用新的 SQL 时间 数据类型。 在 DirectQuery 模式下,引用具有此数据类型的列的公式将返回错误。 时间数据列无法导入内存中模型。

但是,在 PowerPivot 和缓存模型中,引擎有时会将时间值强制转换为可接受的数据类型,并且公式返回结果。

此行为会影响使用日期列作为参数的所有函数。

货币

在 DirectQuery 模式下,如果算术运算的结果具有 Currency 类型,则该值必须位于以下范围内:

  • 最小值:-922337203685477.5808

  • 最大值:922337203685477.5807

组合货币和实数数据类型
例: Currency sample 1

如果 CurrencyReal 类型相乘,并且结果大于9223372036854774784(0x7ffffffffffffc00),则 DirectQuery 模式不会引发错误。

在内存中模型中,如果结果的绝对值大于 922337203685477.4784,则引发错误。

操作导致超出范围的值
例: Currency sample 2

如果对任意两个货币值执行的作导致值超出指定范围,则会在内存中模型中引发错误,但在 DirectQuery 模型中不会引发错误。

将货币与其他数据类型组合在一起
按其他数值类型的值划分货币值可能会导致不同的结果。

聚合函数

在单行表中的统计函数会返回不同的结果。 空表中的聚合函数在内存中的行为也不同于在 DirectQuery 模式下的行为。

对单行表的统计函数
如果用作参数的表包含单个行,在 DirectQuery 模式下,统计函数(如 STDEV 和 VAR)返回 null。

在内存模型中,使用 STDEV 或 VAR 对单行表进行计算的公式会返回除以零错误。

文本函数

由于关系数据存储提供的文本数据类型与 Excel 不同,因此在搜索字符串或使用子字符串时可能会看到不同的结果。 字符串的长度也可以不同。

通常,任何将固定大小列用作参数的字符串作函数都可以有不同的结果。

此外,在 SQL Server 中,某些文本函数支持 Excel 中未提供的其他参数。 如果公式需要遗漏的参数,可能会在内存模型中获得不同的结果或错误。

使用 LEFT、RIGHT 等返回字符的作可能会返回正确的字符,但在其他情况下,或者没有结果
例: LEFT(["text"], 2)

在 DirectQuery 模式下,返回的字符大小写始终与数据库中存储的字母大小写完全一致。 但是,xVelocity 引擎使用不同的算法来压缩和索引值,以提高性能。

默认情况下,使用 Latin1_General 排序规则,该规则不区分大小写但区分重音。 因此,如果小写、大写或混合大小写中存在文本字符串的多个实例,则所有实例都被视为同一字符串,并且仅将字符串的第一个实例存储在索引中。 对存储字符串执行的所有文本函数都将检索索引窗体的指定部分。 因此,示例公式将使用第一个实例作为输入返回整个列的相同值。

表格模型中的字符串存储和排序规则

此行为也适用于其他文本函数,包括 RIGHT、MID 等。

字符串长度会影响结果
例: SEARCH("within string", "sample target text", 1, 1)

如果使用 SEARCH 函数搜索字符串,并且目标字符串比字符串中的字符串长,则 DirectQuery 模式将引发错误。

在内存模型中,返回搜索的字符串,但其长度被截断为<文本>中的长度。

例: EVALUATE ROW("X", REPLACE("CA", 3, 2, "California") )

如果替换字符串的长度大于原始字符串的长度,在 DirectQuery 模式下,公式将返回 null。

在内存中模型中,公式遵循 Excel 的行为,该行为连接源字符串和替换字符串,后者返回 CACalifornia。

字符串中间的隐式 TRIM
例: TRIM(" A sample sentence with leading white space")

DirectQuery 模式将 DAX TRIM 函数转换为 SQL 语句 LTRIM(RTRIM(<column>))。 因此,仅删除前导空格和尾随空格。

相比之下,内存中模型中的同一公式会删除字符串中的空格,并遵循 Excel 的行为。

使用 LEN 函数的隐式 RTRIM
例: LEN('string_column')

与 SQL Server 一样,DirectQuery 模式会自动从字符串列的末尾删除空白:也就是说,它执行隐式 RTRIM。 因此,如果字符串具有尾随空格,则使用 LEN 函数的公式可以返回不同的值。

内存中支持 SUBSTITUTE 的其他参数
例: SUBSTITUTE([Title],"Doctor","Dr.")

例: SUBSTITUTE([Title],"Doctor","Dr.", 2)

在 DirectQuery 模式下,只能使用具有三个 (3) 参数的此函数的版本:对列、旧文本和新文本的引用。 如果使用第二个公式,将引发错误。

在内存中模型中,可以使用可选的第四个参数指定要替换的字符串的实例编号。 例如,只能替换第二个实例等。

REPT操作中的字符串长度限制
在内存中模型中,使用 REPT作生成的字符串长度必须小于 32,767 个字符。

此限制不适用于 DirectQuery 模式。

子字符串作根据字符类型返回不同的结果
例: MID([col], 2, 5)

如果输入文本为 varcharnvarchar,则公式的结果始终相同。

但是,如果文本是固定长度的字符,并且num_chars>的值<大于目标字符串的长度,则 DirectQuery 模式下会在结果字符串的末尾添加一个空白。

在内存中模型中,结果在最后一个字符串字符处终止,没有填充。

DirectQuery 模式下支持的函数

以下 DAX 函数可在 DirectQuery 模式下使用,但具有上一节中所述的限定。

文本函数

串联

找到

莱恩

MID

取代

REPT

替代

修剪

统计函数

计数

STDEV.P

STDEV.S

STDEVX.P

STDEVX.S

VAR.P

VAR.S

VARX.P

VARX.S

日期/时间函数

日期

EDATE

EOMONTH

日期

时间

第二

数学函数和数字函数

天花板

日志

LOG10

电源

DAX 表查询

使用 DAX 表查询来针对 DirectQuery 模型评估公式时,存在一些限制。 DirectQuery 不支持在 ORDER BY 子句中引用同一列两次。 无法创建等效 Transact-SQL 语句,并且查询失败。

在内存模型中,重复 ORDER BY 子句对结果没有影响。

DirectQuery 模式下不支持的函数

在 DirectQuery 模式下部署的模型中不支持某些 DAX 函数。 不支持特定函数的原因可能包括以下任何原因或组合:

  • 基础关系引擎无法执行等效于 xVelocity 引擎执行的计算。

  • 公式不能转换为等效的 SQL 表达式。

  • 转换后的表达式和生成的计算的性能是不能接受的。

以下 DAX 函数不能在 DirectQuery 模型中使用。

路径函数

路径

PATHCONTAINS

PATHITEM

PATHITEMREVERSE

路径长度

杂项函数

COUNTBLANK

固定

格式

兰德公司 (RAND Corporation)

RANDBETWEEN(随机整数函数)

时间智能函数:开始日期和结束日期

DATESQTD

DATESYTD

DATESMTD

DATESQTD

DATESINPERIOD

TOTALMTD

TOTALQTD

TOTALYTD

DATESINPERIOD

去年同期

PARALLELPERIOD

时间智能函数:平衡

期初余额月份

期初余额季度

年初余额

结余月份

季度期末余额

年终结余

时间智能函数:上一个和下一个周期

前一天

上个月

上一季度

上一年

翌日

下个月

下一季度

NEXTYEAR

时间智能函数:跨时间段的周期和计算

STARTOFMONTH

STARTOFQUARTER

年初

ENDOFMONTH

ENDOFQUARTER

ENDOFYEAR

首次约会

最后日期

日期加法函数 (DATEADD)

另请参阅

DirectQuery 模式 (SSAS 表格)