MDX Step by Step 讀書筆記(七) - Performing Aggregation 聚合函數之 Max, Min, Count , DistinctCount 以及其它 TopCount, Generate


MDX 中最大值和最小值

MDX 中最大值和最小值函數的語法和之前看到的 Sum 以及 Aggregate 等聚合函數基本上是一樣的:

Max( {Set} [, Expression])

Min( {Set} [, Expression])

直接看例子,先查詢出所有 Sub Category 下的 Reseller Sales Amount。

 

然后使用 MAX 函數查詢出 Sub Category 下最大的 Reseller Sales Amount。在這里查詢的范圍即 SET 集合是 Sub Category 的所有成員,比較大小的依據是 Reseller Sales Amount,即在 SET 集合中查找 Reseller Sales Amount 的最大值。

比較每個 Sub Category 的 Reseller Sales Amount 和最大值的百分比。

WITH
MEMBER [Measures].[Percent of Max]
AS
([Measures].[Reseller Sales Amount]) / ([Measures].[Max Sales By Subcategory])
, FORMAT_STRING="Percent"
MEMBER [Measures].[Max Sales By Subcategory] AS
Max(
        {[Product].[Subcategory].[Subcategory].Members},
        ([Measures].[Reseller Sales Amount])
   )
SELECT
{
   ([Measures].[Reseller Sales Amount]),
   ([Measures].[Percent of Max])
} ON COLUMNS,
{[Product].[Subcategory].[Subcategory].Members} ON ROWS
FROM [Step-by-Step]        

注意 Max、Min 函數與 TopCount 函數的區別:

Max、Min 函數返回的是在集合中元組對應表達式中最大或者最小的值,但 TopCount 是根據表達式查找集合中的成員。

下面查找 Reseller Sales Amount 最高的那個 Subcategory 成員。

SELECT
{
  ([Measures].[Reseller Sales Amount])        
} ON COLUMNS,
TOPCOUNT
(
  {[Product].[Subcategory].[Subcategory].Members},
  1,
  ([Measures].[Reseller Sales Amount])        
)ON ROWS
FROM [Step-by-Step]

統計集合中的元組 Count( {Set} [, Flag])

與前面的 MDX 聚合函數一樣操作的對象都是集合 SET。Flag 的作用是:如果沒有 Flag 或者指定 INCLUDEEMPTY,那么 Count 函數就直接返回集合中元組的數量;如果指定了 EXCLUDEEMPTY ,那么將返回與當前度量值相關聯的非空的元組。

查詢 Product 級別下所有成員的 Internet Sales Amount 和 Reseller Sales Amount,可以從下面的查詢中看出不是所有產品都有 Internet Sales Amount 或者 Reseller Sales Amount 的銷售記錄。

COUNT 一下各個 Category 下 Product 成員的個數 -

WITH MEMBER [Measures].[Count of Products]
AS
COUNT(
   EXISTING {([Product].[Product].[Product].Members)}
)
SELECT
[Measures].[Count of Products] ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

統計 Category 下 Reseller Sales Amount 大於等於 Internet Sales Amount 的 Products。

WITH MEMBER [Measures].[Count of Products]
AS
COUNT(
   EXISTING {([Product].[Product].[Product].Members)}
)
MEMBER [Measures].[Reseller vs Internet Count of Products]
AS
COUNT(
   FILTER(  
                 EXISTING {([Product].[Product].[Product].Members)},
                 [Measures].[Reseller Sales Amount] >= [Measures].[Internet Sales Amount]
              )
)
SELECT
{[Measures].[Count of Products],
[Measures].[Reseller vs Internet Count of Products]} ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

上面的查詢結果中仍然有不准確的地方,因為在統計過程中包含了 Reseller Sales Amount 為 NULL, Internate Sales Amount 為 NULL 或者兩者都為 NULL 的元組,實際上這類元組應該在統計的時候要被排除掉。

因此,加上 EXCLUDEEMPTY 關鍵字再來查詢一下 -

但是通過觀察最后的查詢結果發現盡管使用了 EXCLUDEEMPTY 關鍵字也沒有什么變化,但是確實有一些 Products 是沒有 Reseller Sales Amount 數據的。其原因就在於這里會造成 Infinite Recursion 錯誤,只不過在這里被自動處理掉了。

有關 Infinite Recursion 的內容可以參看 MDX Step by Step 讀書筆記(五) - Working with Expressions (MDX 表達式) - Infinite Recursion 和 SOLVE_ORDER 原理解析

可以通過 CrossJoin {[Measures].[Reseller Sales Amount]} 來解決這個問題,因為這樣 COUNT 的時候就知道了上下文環境,元組中關聯的度量值對象是 {[Measures].[Reseller Sales Amount]}。

WITH MEMBER [Measures].[Count of Products]
AS
COUNT(
   EXISTING {([Product].[Product].[Product].Members)}
)
MEMBER [Measures].[Reseller vs Internet Count of Products]
AS
COUNT(
    FILTER(
                 EXISTING {([Product].[Product].[Product].Members)},
                [Measures].[Reseller Sales Amount] >= [Measures].[Internet Sales Amount]
              )
)
MEMBER [Measures].[NOEMPTY Reseller vs Internet Count of Products]
AS
COUNT(
      FILTER(
                    EXISTING {([Product].[Product].[Product].Members)},
                    [Measures].[Reseller Sales Amount] >= [Measures].[Internet Sales Amount]
               )* {[Measures].[Reseller Sales Amount]},
      EXCLUDEEMPTY
)
SELECT
{[Measures].[Count of Products],
  [Measures].[Reseller vs Internet Count of Products],
  [Measures].[NOEMPTY Reseller vs Internet Count of Products]} ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

DistinctCount 函數

MDX 提供了另外一種 COUNT 的形式 - DistinctCount,它可以在執行 COUNT 之前先忽略掉空的以及重復的元組然后進行統計。它其實在操作上等同於在 COUNT 函數中使用 DISTINCT 關鍵字:COUNT(DISTINCT ({SET}), EXCLUDEEMPTY)

它的實際語法是:DistinctCount({SET})

但是如果僅僅是需要去掉重復元組后再統計 COUNT ,並且也允許包含空的元組的統計,那么就應該使用:

COUNT(DISTINCT ({SET})) 或者 COUNT(DISTINCT ({SET}), INCLUDEEMPTY)

Generate 函數

Generate ({Set}, Expression) ,Generate 函數在這一篇筆記中已經介紹過了 -

MDX Step by Step 讀書筆記(六) - Building Complex Sets (復雜集合的處理) - Generate 和 Extract 函數的使用

簡單回顧一下這個函數,它類似於一個循環,相當於在集合中的每一個元組都去匹配一下表達式,符合要求的元組留下來並最終和其它一樣滿足要求的元組共同組成一個新的集合 SET 返回。

它還有另外的一種形式可以在聚合中用到:Generate({Set}, Expression [, Delimiter])

在這個形式中,Generate 函數仍然會迭代 SET 集合中的每一個元組並匹配表達式中的內容,符合條件的元組根據 Delimiter 分割符與其它元組形成一個字符串。

WITH
MEMBER [Measures].[Products] AS
Count(
   EXISTING {[Product].[Product].[Product].Members}
)
MEMBER [Measures].[Products List] AS
Generate(
   EXISTING {[Product].[Product].[Product].Members},
   [Product].[Product].CurrentMember.Name,
   " | "
)
SELECT
{
  ([Measures].[Products]),
  ([Measures].[Products List])
} ON COLUMNS,
{[Product].[Subcategory].Members} ON ROWS
FROM [Step-by-Step]

更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果覺得這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM