DAX 联接表系列(二)

DAX联接表系列 之三 : 分组数据

    4、SUMMARIZE 分组数据

        SQL 语句的GROUP– 按条件分组,在 DAX中是通过SUMMARIZE函数来实现的。本文演示如何使用SUMMARIZE或其他替代语法来对数据进行分组。考虑以下 SQL 查询:

SELECT  OrderDate, 
SUM(SalesAmount) AS Sales
FROM  FactInternetSales
GROUP BY  OrderDate

它对应于DAX查询中使用SUMMARIZE:

EVALUATE
SUMMARIZE (‘Internet Sales’,
‘Internet Sales'[Order Date],  “Sales”, SUM ( ‘Internet Sales'[Sales Amount] ))

    5、其他方式分组数据

你还可以使用产生相同结果的其他语法, 即使它在语义上不是相同的, 例如你稍后将会看到的:

EVALUATE
ADDCOLUMNS (VALUES ( ‘Internet Sales'[Order Date] ),
“Sales”, CALCULATE ( SUM ( ‘Internet Sales'[Sales Amount] ) ))

      使用 ADDCOLUMNS 时需要应用CALCULATE,因为必须将行筛选 (由 [Order Date] 列中的迭代定义) 转换为列表筛选。这在SUMMARIZE中不需要, 因为SUMMARIZE定义的表达式已经在指定的组的当前筛选中执行。
      当分组操作中涉及更多的表时, ADDCOLUMNS 和SUMMARIZE之间的语义差异就变得更清楚。例如, 请考虑以下 SQL 查询:

SELECT  d.CalendarYear,
SUM(s.SalesAmount) AS Sales
FROM  FactInternetSales s
LEFT JOIN DimDate d  ON s.OrderDateKey = d.DateKey
GROUP BY  d.CalendarYear

      这种情况下, 如果数据模型在 DimDate 和 Internet Sales之间有关系, 则 DAX表达式会隐式使用它。这是相应的 DAX语法 (仅保证数据显示在下表中的顺序):

      EVALUATE
      SUMMARIZE ( ‘Internet Sales’,  ‘Date'[Calendar Year],
    “Sales”, SUM ( ‘Internet Sales'[Sales Amount] ))
      ORDER BY ‘Date'[Calendar Year]

      你在Adventure Works中获得此结果的SQL 2012表格模型 :

《DAX 联接表系列(二)》

      作为第一个参数传递的表与传递用于分组数据的列所在的表联接。因此, SUMMARIZE相当于定义DISTINCT 与 GROUP BY等效的SQL操作, 并在表和一个或多个查找表之间包含一个LEFT  JOIN–左联接。 你可以使用其他 DAX语法来替代SUMMARIZE:

EVALUATE
ADDCOLUMNS (  VALUES ( ‘Date'[Calendar Year] ),
“Sales”, CALCULATE ( SUM ( ‘Internet Sales'[Sales Amount] ) ))
ORDER BY ‘Date'[Calendar Year]

      但是, 这将返回不同的结果, 本例中,包括在 “Date” 表中定义的’Date'[Calendar Year]列  (在 Internet Sales表中没有任何相应的数据)。

《DAX 联接表系列(二)》

    这是因为最后一个DAX查询对应于以下SQL语法:

      SELECT  d.CalendarYear,
      SUM(s.SalesAmount) AS Sales
      FROM  DimDate d
      LEFT JOIN FactInternetSales s
      ON d.DateKey = s.OrderDateKey
      GROUP BY d.CalendarYear

      正如所看到的,SUMMARIZE并不需要执行JOIN联接,但是不同的DAX语法会执行不同的连接类型。在本例,LEFT JOIN–左连接中使用的表是反向的表。

        按:SUMMARIZE()总是给出元数据表里的唯一值的列,可看成是VALUES()的扩展,即与VALUES()给出唯一值的单个列不同,SUMMARIZE()可针对2列或更多列 。

        最后,考虑以下SQL查询中的条件:
        SELECT  d.CalendarYear,
        SUM(s.SalesAmount) AS Sales
        FROM DimDate d 
        LEFT JOIN FactInternetSales s
        ON d.DateKey = s.OrderDateKey
        GROUP BY  d.CalendarYear
        HAVING  SUM(s.SalesAmount) > 8000000
        ORDER BY  d.CalendarYear

          此查询仅返回销售额大于800万的年份:

《DAX 联接表系列(二)》

        DAX里没有对应于HAVING(条件)的语法。毕竟, 通过将 WHERE条件应用于子查询, 你可能会在 SQL 中获得相同的结果。在 DAX中, 编写与HAVING相对应的语法: 只需要使用FILTER筛选来引用SUMMARIZE或 ADDCOLUMNS 函数调用的结果即可, 如下面的示例所示:

        EVALUATE
        FILTER (
          ADDCOLUMNS (VALUES ( ‘Date'[Calendar Year] ),
        “Sales”,
          CALCULATE ( SUM ( ‘Internet Sales'[Sales Amount] ) ) ), [Sales] > 8000000)
          ORDER BY ‘Date'[Calendar Year]

        EVALUATE
        FILTER (
        SUMMARIZE (  ‘Internet Sales’, ‘Date'[Calendar Year],
          “Sales”,
SUM ( ‘Internet Sales'[Sales Amount] )), [Sales] > 8000000)
          ORDER BY ‘Date'[Calendar Year]

      重要的是要记住: 公式引擎会引用筛选器结果应用于计算。如果可以的话, 最好使用CALCULATE或 CALCULATETABLE 来应用筛选器。但是,本例中, 你必须使用FILTER筛选器, 因为聚合结果不能作为CALCULATE或 CALCULATETABLE 中的筛选器参数的一部分。

   DAX联接表系列 之四: DAX筛选

    6、FILTER与CALCULATETABLE

       SQL 语句的 WHERE 条件有两个对应的 DAX函数:FILTER 和 CALCULATETABLE。在本文中, 将探讨它们之间的差异,并提供一些最佳的使用方法。请考虑以下 SQL 语法:

        SELECT * FROM DimProduct
        WHERE Color = ‘Red’

        它对应于使用FILTER的此 DAX查询:

        EVALUATE
        FILTER ( Product, Product[Color] = “Red” )

        您也可以使用 CALCULATETABLE 的DAX查询:

          EVALUATE
          CALCULATETABLE ( Product, Product[Color] = “Red” )

      与初始的那个简单 SQL 查询一样, 两个相应的 DAX选项之间没有语义差异。但是, 当存在其他表达式或更复杂的筛选条件时, 就会看到不同的行为。考虑这样一个双重筛选器:

        SELECT * FROM DimProduct
        WHERE Color = ‘Red’ AND ListPrice > 1000

      该查询对应的使用FILTER筛选器的DAX,有两个选项。最简单的方式是将相同的逻辑表达式应用于单个筛选器里:
        EVALUATE
        FILTER (  Product,
        AND ( Product[Color] = “Red”, Product[ListPrice] > 1000 ))

      使用此方法, 产品中的每一行都应用逻辑条件 ([Color] = “Red”AND [ListPrice] > 1000), 即将它在内部进行某些优化, 以减少进行条件比较的次数。这是使用 CALCULATETABLE 的相应解决方案:
        EVALUATE
        CALCULATETABLE (  Product,
        Product[Color] = “Red”, Product[List Price] > 1000)

      CALCULATETABLE 中的筛选器参数总是放置在AND(并)的逻辑条件中,即使FILTER筛选器与 CALCULATETABLE 所产生的结果相同, 它们的性能也可能不同。
    (1)如果单个列上的每个逻辑条件返回的值的数量相对较小, CALCULATETABLE 可能会更快。
    (2)CALCULATETABLE 中的每个筛选器参数都对应于单个列上的内部筛选器。前面的 CALCULATETABLE 语法在内部被重写为:
      EVALUATE
      CALCULATETABLE (Product,
      FILTER ( ALL ( Product[Color] ), Product[Color] = “Red”  ),
      FILTER ( ALL ( Product[List Price] ), Product[List Price] > 1000))

    (3)不能说使用 CALCULATETABLE 比使用 FILTER要好。因每个 CALCULATETABLE 内部都包含一个或多个筛选器。 因此,其性能通常由每个筛选器的粒度决定 (即使 DAX引擎可能会执行进一步的优化)。
    (4)在 OR(或) 条件的情况下, 即使在 CALCULATETABLE 中, 也应将整个逻辑条件(包括内部的筛选条件)编写为单个条件中。请考虑以下 SQL 语句:

        SELECT * FROM DimProduct
        WHERE Color = ‘Red’ OR Weight > 100
        使用FILTER筛选的相应 DAX语法如下:

        EVALUATE
        FILTER ( Product,
        OR ( Product[Color] = “Red”, Product[Weight] > 1000 ))

      相应的 CALCULATETABLE 版本则需要显式筛选器参数, 以便指定包含同一表的两个列的逻辑条件 (在本例中, 不可能存在自动复制的筛选)。
        EVALUATE
        CALCULATETABLE ( Product,
        FILTER ( Product, OR ( Product[Color] = “Red”, Product[Weight] > 1000 ))

        此时, 你可能又认为FILTER筛选器使用起来更简单些。但是, 由于存在不同行为的嵌套计算, 因此,应始终考虑 CALCULATETABLE 选项。例如, 请考虑以下 SQL 查询, 它返回总销售额大于 10万的红色的产品,并且该产品在日历年2006中的平均销售额大于3000。

      SELECT *  FROM DimProduct p
      WHERE Color = ‘Red’
      AND ( SELECT SUM([Sales Amount])
        FROM [Fact Internet Sales] s
      INNER JOIN DimDate d
      ON s.OrderDateKey = d.DateKey
      WHERE s.ProductKey = p.ProductKey
      AND d.CalendarYear = 2006 ) > 100000
        AND ( SELECT AVG([SalesAmount])
        FROM [FactInternetSales] s
        INNER JOIN DimDate d
        ON s.OrderDateKey = d.DateKey
        WHERE s.ProductKey = p.ProductKey
        AND d.CalendarYear = 2006  ) > 3000

      单独使用FILTER的等效 DAX表达式要比 SQL 表达式短。但是, 你仍可以在两个计算中定义[Calendar Year]–日历年份筛选器 (SUM–总和与AVERAGE–平均值):

        EVALUATE
        FILTER (
        FILTER ( Product, Product[Color] = “Red” ),
        AND (
        CALCULATE (SUM ( ‘Internet Sales'[Sales Amount] ),
        ‘Date'[Calendar Year] = 2006  ) > 100000,
        CALCULATE (  AVERAGE ( ‘Internet Sales'[Sales Amount] ),
        ‘Date'[Calendar Year] = 2006  ) > 3000 ) )

      使用 CALCULATETABLE, 筛选参数 ([Color]颜色和[Calendar Year]) 将应用于第一个参数中指定的整个表达式。因此, 下面的 DAX查询的FILTER筛选器中的两个计算表达式不必在日历年中包含筛选器, 因为它是从外部 CALCULATETABLE 筛选器 “继承”来 的。

        EVALUATE
        CALCULATETABLE (
        FILTER (  Product,
      AND (
        CALCULATE ( SUM ( ‘Internet Sales'[Sales Amount] ) ) > 100000,
        CALCULATE ( AVERAGE ( ‘Internet Sales'[Sales Amount] ) ) > 3000 ) ),                              Product[Color] = “Red”,’Date'[Calendar Year] = 2006 ) 

      使用 CALCULATETABLE 将FILTER筛选器传递到其第一个参数中嵌入的所有表达式。这会简化查询并使语法更简洁。 但是,需要特别注意的是, 外部 CALCULATETABLE 或CALCULATE语句操作筛选器并可能影响到任何内部表达式。

    原文作者:PowerBI非官方
    原文地址: https://www.jianshu.com/p/cc1df26494b5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞