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

GENERATE 和 GENERATEALL

GENERATE 函数对 Table1 的每一行计算 Table2,返回 Table1 中每一行与 Table2 的相应行之间生成的笛卡尔积。GENERATE 使用两个表表达式:

GENERATE

GENERATE ( <Table1>, <Table2> )
参数 属性 描述
Table1 GENERATE 使用的基础表.
Table2 在 Table1 的每一行计值的表表达式

GENERATEALL

GENERATEALL(<Table1>, <Table2>)
参数 属性 描述
Table1 GENERATEALL 使用的基础表.
Table2 在 Table1 的每一行计值的表表达式

GENERATEALL 与 GENERATE 的计值过程相同,仅在对空行的处理上有所区别。当对<Table2>的计算返回空记录时,GENERATEALL 将来自<Table1>的当前行包含在结果中。这与 GENERATE 不同,后者移除所有空值对应的<Table1>当前行。

另外,与 CROSSJOIN 类似,GENERATE 系列函数的 Table1 和 Table2 中的所有列名不能有重复,否则将报错。

示例用法

GENERATE 的一个简单用法是生成包含产品类别和子类别的所有有效组合的表,你可以使用这个查询

EVALUATE
GENERATE (
    'Product Category',
    RELATEDTABLE ( 'Product Subcategory' )
)

GENERATE 调用的 Table2 通常包含 RELATEDTABLECALCULATETABLE 函数,以便使用 Table1 迭代的行上下文进行上下文转换

如果在第二参数中省略 RELATEDTABLE,将得到与 CROSSJOIN 相同的结果,因为没有通过 RELATEDTABLE 将行上下文转换筛选上下文,(RELATEDTABLE 是 CALCULATEDTABLE 简化版的别名)

实际上,以下查询是等效的:

EVALUATE
GENERATE( 'Product Category', 'Product Subcategory' )

EVALUATE
CROSSJOIN( 'Product Category', 'Product Subcategory' )

GENERATE 的一个更有趣的例子是如何得到一个表,使其包含每年销售量排名前两位的产品。以下查询对每一年执行 TOPN 函数,计算每一年中对应产品的排名:

EVALUATE
GENERATE (
    VALUES ( 'Date'[Calendar Year] ),
    TOPN (
        2,
        SUMMARIZE (
            RELATEDTABLE ( Sales ),
            Product[Product Name]
        ),
        CALCULATE (
            SUM ( Sales[Quantity] )
        )
    )
)

这里需要注意的是,查询只返回那些至少包含一笔销售记录的年份。如果你还希望在销售表中包含没有任何销售记录的年份,可以使用 GENERATEALL 代替 GENERATE,如以下查询所示:

EVALUATE
GENERATEALL (
    VALUES ( 'Date'[Calendar Year] ),
    TOPN (
        2,
        SUMMARIZE (
            RELATEDTABLE ( Sales ),
            Product[Product Name]
        ),
        CALCULATE (
            SUM ( Sales[Quantity] )
        )
    )
)

如果你习惯使用 SQL,你可以认为 GENERATE 函数类似于 SQL 中的 CROSS APPLY 条件,而 GENERATEALL 函数类似于 SQL 中的 OUTER APPLY 条件

9
说点什么

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

高老师,如下图上,我的利润表,要把类似比率的科目带上。但是我的源数据里没有现成的。需要怎么操作哇?我知道用Divide函数写度量值。但是,显示起来就不是想要的样子了。

134.png
成员
lyliuyouyang

其实这个generate还是稍微有点抽象了,我看到那个取年度前二的例子才有一种醒悟的感觉,倒不是理解了,反倒是因为这个案例的目的,生成每年度的前二,目前我用别的函数还暂时无法写不出来,所以觉得这个函数在这方面有奇效?第一个包含产品类别和产品子类的有效组合好像summerize可以实现?对于取每年度前2这个例子,个人的理解是这个函数比较强大的地方是,topn这个函数返回的2列的表是和年度没有关系的,但是作为第二参数,直接交给generate,此时generate可以按照第一个表参数去重新计算第二个表参数topn,从而达到目的?不知道我的理解是不是有偏差。在学这个函数的时候脑袋里总会浮现出group by的身影,类比一下group by的等价形式(对数据进行二次聚合):
    VAR table2 =
        ADDCOLUMNS (
            VALUES ( ‘追加'[劳务队名称] ),
            “平均”, CALCULATE (
                AVERAGEX (
                    ADDCOLUMNS (
                        SUMMARIZE ( ‘追加’, ‘追加'[劳务队名称], ‘日期表'[年份] ),
                        “金额”, CALCULATE ( MAX ( ‘追加'[计价金额] ) )
                    ),
                    [金额]
                )
            )
        )
在这个例子里,用summerize和max生成的值,里面包含了外层第二次聚合的 劳务队名称,所以外层的values(劳务队名称)迭代函数可以求得结果。
但是generate最里面一层没有年份的维度,只是用到了relatedtable,外部第一个表表参数直接把values(年份)作为第一表参数就可以得到想要的结果。
虽然generate第二个参数只能是表,转换不了group by的等价形式,不过还是希望能帮忙解答一下这两种写法的联系和区别。作为初学者我不知道怎么就把这两个不太相关的东西放在一起了,麻烦解答一下疑惑,谢谢!

成员
lyliuyouyang

你好,我刚试着又用geneate写了一下,因为geneate第二参数只能是表函数,我用row嵌套了一下,发现是可以出结果的,代码如下: VAR table4 = GENERATE ( VALUES ( ‘追加'[劳务队名称] ), ROW ( “平均… 阅读更多 »

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数