数据沿袭实际上存在DAX中的每个角落,它的设计如此好,以至于很多开发人员在不知情的情况使用。

DAX使用数据沿袭来维护关于列值来源的信息。数据沿袭实际上是一个标签(Tag),分配给表中的每一列,此Tag用于标识数据模型中的原始列,即列的值源自于该列。通过数据沿袭,DAX可以利用现有的关系来过滤数据模型。

对列的简单引用会保留数据沿袭,对列执行运算会破坏数据沿袭。

1,对列的简单引用会保留数据沿袭

例如,以下查询返回 Product 表中的不同类别:

EVALUATE VALUES ( 'Product'[Category] )

VALUES 返回的表包含 8 个字符串,然而,它们不仅仅是字符串,DAX还知道这些字符串源自 Product[Category] 列。作为 Product 表的沿袭,它们继承了Product可以通过关系传播来过滤数据模型中其他表的能力,这就是在迭代函数中迭代VALUES ( Product[Category] ) ,创建的行上下文能够转换为过滤 Sales 表的原因。

考虑以下查询,通过把行上下文转换为筛选上下文,计算每个Categoyr的销售额。VALUES函数返回的表之所以能够和Sales表进行关联,原因就是VALUES函数会保持数据沿袭,这使得Product和Sales之间的关系不变。

EVALUATE
ADDCOLUMNS (VALUES ( 'Product'[Category] ),"Amt", [Sales Amount]
)

2,数据沿袭跟列名和内容无关,仅跟原始列有关系

举个例子,使用DATATABLE创建一个静态表Category,该表和Sales之间没有任何关系,这使得列值“Audio”本身无法过滤 Sales,可以通过运行以下查询轻松检查这一点:

EVALUATE
VAR Categories =DATATABLE ("Category", STRING,{{ "Category" },{ "Audio" },{ "TV and Video" },{ "Computers" },{ "Cameras and camcorders" },{ "Cell phones" },{ "Music, Movies and Audio Books" },{ "Games and Toys" },{ "Home Appliances" }})
RETURNADDCOLUMNS ( Categories, "Amt", [Sales Amount] )

列名和列内容都不重要,真正重要的只是列的数据沿袭,换句话说,值源自于的那个原始列是重要的。如果重命名列,仍会保留数据沿袭。 实际上,以下查询为每一行返回不同的值:

EVALUATE
ADDCOLUMNS (SELECTCOLUMNS (VALUES ( 'Product'[Category] ),"New name for Category", 'Product'[Category]),"Amt", [Sales Amount]
)

由于列“New name for Category”保留了列Product[Category]的数据沿袭,因此,输出的结果按照Product[Caegory]统计销售额,尽管结果中的列名与原始列名不同。

3,对列执行运算会破坏数据沿袭

只要表达式仅由一个列引用组成,就会保持数据沿袭。例如,在前面的表达式中向 Product[Category] 添加一个空字符串不会更改列内容,但会破坏数据沿袭。

在下面的代码中,列“New name for Category”的来源是一个表达式,而不仅仅是一个列引用,因此,新列的数据沿袭与数据模型的任何列都不相关。

EVALUATE
ADDCOLUMNS (SELECTCOLUMNS (VALUES ( 'Product'[Category] ),"New name for Category", 'Product'[Category] & ""),"Amt", [Sales Amount]
)

4,每列都有自己的数据沿袭

每列都有自己的数据沿袭,即使一个表包含来自不同表的列。因此,表表达式的结果可以一次把过滤器应用于多个表。 这在以下查询中清晰可见,表中包含 Product[Category] 和 Date[Calendar Year],这两列都通过上下文转换产生的筛选上下文把它们的筛选器应用于度量[Sales Amount]。

EVALUATE
FILTER (ADDCOLUMNS (CROSSJOIN (VALUES ( 'Product'[Category] ),VALUES ( 'Date'[Calendar Year] )),"Amt", [Sales Amount]),[Amt] > 0
)

结果显示给定的类别和年份的销售额。Category 和 Calendar Year 列都在主动过滤 Sales Amount 度量。

5,使用TREATS函数修改数据沿袭

即使DAX引擎以完全自动的方式保存和维护数据沿袭,开发人员也可以选择更改表的数据沿袭,这就是 TREATAS函数的用途。TREATAS 接受一个表作为它的第一个参数,然后是一个列引用列表。

TREATAS(table_expression, <column>[, <column>[, <column>[,…]]]} )  

TREATS函数用于操作数据沿袭,把列和原始列之间建立映射关系,在使用TREATS函数时,注意:

  • TREATAS返回一个表,该表包含<column>参数中的所有行,这些行也在 table_expression 中。
  • 返回的表中的列和<coloumn>参数指定的列建立数据沿袭映射。如果table_expression 中的某些值与用于应用数据沿袭的<column>参数中的有效值不匹配,那么TREATAS 会从table_expression 中删除这些值。

例如,以下查询构建了一个包含字符串列表的表,其中“Computers and geeky stuff”不对应于模型中的任何类别,当使用 TREATAS 把表的数据沿袭强制为 Product[Category]时:

EVALUATE
VAR Categories =DATATABLE ("Category", STRING,{{ "Category" },{ "Audio" },{ "TV and Video" },{ "Computers and geeky stuff" },{ "Cameras and camcorders" },{ "Cell phones" },{ "Music, Movies and Audio Books" },{ "Games and Toys" },{ "Home Appliances" }})
RETURNADDCOLUMNS (TREATAS (Categories,'Product'[Category]),"Amt", [Sales Amount])

由于数据模型没有名为“Computers and geeky stuff”的类别,因此 TREATAS 必须从输出中删除该行以完成数据沿袭转换。

6,操作数据沿袭

现在我们已经了解了数据沿袭是什么以及如何使用 TREATAS 对其进行操作,现在是时候来看一个示例,其中 TREATAS 和数据沿袭操作生成了非常优雅的 DAX 代码。

考虑计算销售额的要求,只过滤每个产品的第一天的销售额。相同的计算逻辑对客户、商店或任何其他维度都有意义,但我们仅考虑此示例中的产品。

每种产品都有不同的首次销售日期,一种选择是按照产品计算每个产品的第一个销售日期,然后计算该日期的销售额,最后汇总所有产品的结果。 以下代码可以正常工作:

FirstDaySales v1 :=
SUMX ('Product',VAR FirstSale =CALCULATE (MIN ( Sales[Order Date] ))RETURNCALCULATE ([Sales Amount],'Date'[Date] = FirstSale)
)

结果是正确的,但上面的代码不是最优的。实际上,它迭代 Product 表,为每个产品生成上下文转换,还在 Date 上应用过滤器,而不是利用任何关系。并不是说这是糟糕的代码,它只是没有它应该的那么优雅。 我们现在将看到该度量的替代版本以更有效的方式返回相同的结果。

朝着正确方向迈出的第一步是构建一个包含产品名称和相应产品的首次销售日期的表ProductsAndFirstDate,然后使用这个表ProductsAndFirstDate对Sales表应用过滤器。下面的代码与之前的代码相比是一个改进,但它仍然不是最优的,因为 SUMX 仍然为每个产品生成一个上下文转换:

FirstDaySales v2 :=
VAR ProductsWithSales =SUMMARIZE (Sales,'Product'[Product Name])
VAR ProductsAndFirstDate =ADDCOLUMNS (ProductsWithSales,"Date First Sale", CALCULATE (MIN ( Sales[Order Date] )))
VAR Result =SUMX (ProductsAndFirstDate,VAR DateFirstSale = [Date First Sale]RETURN CALCULATE ([Sales Amount],'Date'[Date] = DateFirstSale))
RETURN Result

但是,请将注意力集中在 ProductsAndFirstDate 变量上,这是ADDCOLUMNS函数的结果,它包含产品名称和日期。如果把这个表用作 CALCULATE 的过滤器参数,它将过滤产品和日期。 因此,这个版本(不幸的是,这是错误的)会更好:

FirstDaySales v3 (wrong) :=
VAR ProductsWithSales =SUMMARIZE (Sales,'Product'[Product Name])
VAR ProductsAndFirstDate =ADDCOLUMNS (ProductsWithSales,"Date First Sale", CALCULATE (MIN ( Sales[Order Date] )))
VAR Result =CALCULATE ([Sales Amount],ProductsAndFirstDate)
RETURN Result

如您所见,SUMX 迭代从算法中消失了。 然而,这个版本的代码是有缺陷的,因为它返回与销售金额相同的值,而没有应用任何过滤器。实际上,虽然ProductsAndFirstDate包含两列 Product Name和First Date,但从数据沿袭的角度来看,Product Name是 Product[Product Name]的数据沿袭,而 First Sale 列中的日期不是Date[Date]列的数据沿袭,这是 MIN 表达式的结果。 First Sale 列有自己的数据沿袭,与数据模型中的其他表无关。

解决方案是更改 First Sale 列的数据沿袭,使其强制为 Date[Date]。TREATAS 正是为此而存在的。 正确的优化措施如下:

FirstDaySales v4 :=
VAR ProductsWithSales =SUMMARIZE (Sales,'Product'[Product Name])
VAR ProductsAndFirstDate =ADDCOLUMNS (ProductsWithSales,"First Sale", CALCULATE (MIN ( Sales[Order Date] )))
VAR ProductsAndFirstDateWithCorrectLineage =TREATAS (ProductsAndFirstDate,'Product'[Product Name],'Date'[Date])
VAR Result =CALCULATE ([Sales Amount],ProductsAndFirstDateWithCorrectLineage)
RETURN Result

虽然最后一个解决方案不是该模式的主要解决方案,但是,在性能方面,这段代码几乎是最佳的。在熟悉数据沿袭之后,请开始考虑在DAX开发中使用上述解决方案,利用数据沿袭使过滤器从一个表移动到另一个表,以写出更高效的代码。

参考文档:

Understanding data lineage in DAX

DAX 第八篇:【翻译】数据沿袭(Data Lineage )相关推荐

  1. 星尘小组第八周翻译-数据页和数据行

    数据页和数据行 数据库中的空间被划分为8KB的逻辑页面.这些页面从0开始连续编号,可以通过指定文件ID和页码引用它们.页面编号始终是连续的,因此当SQL Server增长数据库文件时,新页面的编号从文 ...

  2. CYQ.Data 轻量数据层之路 使用篇-MAction 数据查询 视频 D (二十一)

    2019独角兽企业重金招聘Python工程师标准>>> 说明: 本次录制主要为使用篇:CYQ.Data 轻量数据层之路 使用篇二曲 MAction 数据查询(十三)   的附加视频教 ...

  3. 数据工程 数据科学_10篇关于数据科学和数据工程的伟大文章

    数据工程 数据科学 数据科学和程序设计是一个快速发展的专业,很难跟上Google,Uber,Netflix和一位工程师的所有文章. 过去几周我们一直在阅读一些内容,并希望在2019年4月这一周分享一些 ...

  4. sql isnull怎么没用_SQL语言在数据工程(Data Engineering)中的运用(一)

    我与SQL的纠葛好几年前就开始了,在不断炒冷饭的过程中终于接了几个不错的项目,把冷饭变成了温饭.今天就借此机会,与大家分享一下自己在项目中的心路历程,从中学习到的SQL在数据工程中的运用,代码分享,代 ...

  5. 数据挖掘(data mining),机器学习(machine learning),和人工智能(AI)的区别是什么? 数据科学(data science)和商业分析(business analytics

    数据挖掘(data mining),机器学习(machine learning),和人工智能(AI)的区别是什么? 数据科学(data science)和商业分析(business analytics ...

  6. Python之路【第八篇】:堡垒机实例以及数据库操作

    Python之路[第八篇]:堡垒机实例以及数据库操作 堡垒机前戏 开发堡垒机之前,先来学习Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于 ...

  7. 数据湖 data lake_在Data Lake中高效更新TB级数据的模式

    数据湖 data lake GOAL: This post discusses SQL "UPDATE" statement equivalent for a data lake ...

  8. as cast float server sql_SQL语言在数据工程(Data Engineering)中的运用(一)

    我与SQL的纠葛好几年前就开始了,在不断炒冷饭的过程中终于接了几个不错的项目,把冷饭变成了温饭.今天就借此机会,与大家分享一下自己在项目中的心路历程,从中学习到的SQL在数据工程中的运用,代码分享,代 ...

  9. 使用MapReduce统计一篇微博数据的点赞次数,并且输出前五个最高的点赞数量。

    一个MapReduce写了一个下午,调试运行了不下20次了,我靠,真是闹心,差点整崩溃,在最绝望的时候给出了最好的答案. 需求: 使用MapReduce统计一篇微博数据的点赞次数,并且输出前五个最高的 ...

最新文章

  1. CADisplayLink 及定时器的使用
  2. 大学生创新创业大赛案例_第五届“南博杯”大学生创新创业大赛决赛举行
  3. 001_JavaScript简介
  4. SAP Spartacus org unit table不同区域focus然后回车的行为差异
  5. how does framework know the Advertisement model should be used to parse json
  6. 服务发现技术是如何演进出来的?
  7. qemu搭建arm运行linux内核,centos使用qemu搭建ARM64运行环境
  8. 华为nova5iotg功能使用_原来华为EMUI10输入法这么强大!使用这个功能,一分钟能打300字...
  9. 五大维度深掘工业互联网数据价值
  10. WPF 辅助开发工具
  11. Docker修改MySQL默认端口
  12. STM32最小系统下载程序方法
  13. Windows11企业版22000.1精简版(附下载链接)
  14. 基于人脸识别录入 人脸图片识别 及测试的效果
  15. linux系统棋牌搭建教程,幼麟棋牌四川麻将搭建教程补充
  16. GMail为什么可以屹立不倒?
  17. Apple Pay支付流程详解
  18. cdr怎么把矩形去掉一个边_cdr怎么消除图形的边框?
  19. raptor流程图赋值语句_RAPTOR和流程图.ppt
  20. 集成融云RongCloud视频通话功能PC端

热门文章

  1. __attribute__((section(”XXXX“)))的编译属性---section
  2. Android实现语音识别成中文
  3. IPv6连接测试通过,但是无法ping成功问题解决(记录)
  4. Java Message Servicec - ActiveMQ
  5. 数据结构复习 ---- 邻接表
  6. Notepad++显示所有字符:空格换行
  7. Python pandas读取excel单元格数据,显示不全问题
  8. hostapd对WIFI 热点(AP)的配置方法
  9. 贾扬清:云原生是数据智能的必然
  10. 中科院基于gpt的学术优化网站搭建教程