MDX Step by Step 讀書筆記(四) - Working with Sets (使用集合)


1. Set  - 元組的集合,在 Set 中的元組用逗號分開,Set 以花括號括起來,例如:

{ ([Product].[Category].[Accessories]), ([Product].[Category].[Bikes]), ([Product].[Category].[Clothing]), ([Product].[Category].[Components]) }

從這個例子中可以看到Set的幾個特點:

  • 一個Set 中可以包含一個或者多個 Tuple 元組
  • 在 Set 中的每一個元組所包含的Member 成員都對應的引用的是同一個層次結構,在這個例子中引用的是 [Product].[Category]

這種也是Set

{ ([Product].[Category].[Accessories][Date].[Calendar]. [CY 2004]), ([Product].[Category].[Bikes][Date].[Calendar].[CY 2002]), ([Product].[Category].[Clothing][Date].[Calendar].[CY 2003]), ([Product].[Category].[Components][Date].[Calendar].[CY 2001]) }

從這里可以看到 Set:

  • 在包含的元組中,元組中的成員可以有一個或者多個,但是元組中的成員順序和其它元組中成員的順序應該相同。這里所講的成員是指在Set中所有元組中第一個成員引用的層次結構都是 [Product].[Category] 並且第二個成員引用的都是 [Date].[Calendar] 屬性層次結構。成員引用屬性層次結構的順序不能改變,必須相同。

2. 案例分析 – 查詢 Accessories,Bikes,Clothing,Components 四類產品在2002-2004 財年美國的零售額。行軸為四類產品,列軸為 2002-2004 財年+美國

SELECT { ([Date].[Calendar].[CY 2002][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2003][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2004][Geography].[Country].[United States]) } ON COLUMNS, { ([Product].[Category].[Accessories]), ([Product].[Category].[Bikes]), ([Product].[Category].[Clothing]), ([Product].[Category].[Components]) } ON ROWS FROM [Step-by-Step]

第一個 Set 中包含了三個元組,每一個元組都包含兩個成員引用,第一個成員引用財年層次結構,第二個成員引用了地理緯度中的國家層次結構。第二個 Set 包含了四個元組,每一個元組都只包含一個成員,但是都引用到了同一個Category 層次結構。

錯誤的引用:

  1. 元組中的成員引用了不一致的層次結構
SELECT { ([Date].[Calendar].[CY 2002][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2003][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2004][Geography].[Country].[United States]) } ON COLUMNS, { ([Product].[Category].[Accessories]), ([Product].[Category].[Bikes]), ([Product].[Category].[Clothing]), ([Product].[Category].[Components]), ([Product].[Subcategory].[Mountain Bikes]) } ON ROWS FROM [Step-by-Step]

錯誤消息: Executing the query...

Members,tuples or sets must use the same hierarchies in the function.

Execution complete

解釋 - 第二個Set 中的元組 ([Product].[Subcategory].[Mountain Bikes]) 中的成員所引用的層次結構和其它元組中的成員所引用的層次結構不一致,導致錯誤。  

  2. 元組中的成員在引用層次結構時的順序不一致

SELECT { ([Geography].[Country].[United States][Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2004][Geography].[Country].[United States]) } ON COLUMNS, { ([Product].[Product Categories].[Accessories]), ([Product].[Product Categories].[Bikes]), ([Product].[Product Categories].[Clothing]), ([Product].[Product Categories].[Components]), ([Product].[Product Categories].[Mountain Bikes]) } ON ROWS FROM [Step-by-Step]

錯誤消息:

Executing the query...

Members,tuples or sets must use the same hierarchies in the function.

Execution complete

解釋:第一個 Set 中的第一個元組中的成員引用的層次結構順序和第二個第三個元組中的成員引用的屬性層次結構不一致,順序不能顛倒,必須保持完全一致。

  3. 重復的元組是允許的,這樣查詢出來的結果就會多一條記錄

SELECT { ([Geography].[Country].[United States][Date].[Calendar].[CY 2004]), ([Geography].[Country].[United States][Date].[Calendar].[CY 2003]), ([Geography].[Country].[United States][Date].[Calendar].[CY 2002]) } ON COLUMNS, { ([Product].[Product Categories].[Accessories]), ([Product].[Product Categories].[Accessories]), ([Product].[Product Categories].[Bikes]), ([Product].[Product Categories].[Clothing]), ([Product].[Product Categories].[Components]), ([Product].[Product Categories].[Mountain Bikes]) } ON ROWS FROM [Step-by-Step]

3. Distinct 函數

在一個有着復雜邏輯的MDX 查詢中很有可能在一個 Set 中出現重復的元組,可以通過Distinct 函數去掉重復的元組 Distinct({Set})

SELECT { ([Geography].[Country].[United States][Date].[Calendar].[CY 2004]), ([Geography].[Country].[United States][Date].[Calendar].[CY 2003]), ([Geography].[Country].[United States][Date].[Calendar].[CY 2002]) } ON COLUMNS, DISTINCT( { ([Product].[Product Categories].[Accessories]), ([Product].[Product Categories].[Accessories]), ([Product].[Product Categories].[Bikes]), ([Product].[Product Categories].[Clothing]), ([Product].[Product Categories].[Components]), ([Product].[Product Categories].[Mountain Bikes]) } ) ON ROWS FROM [Step-by-Step]

 查詢結果

4. 理解 SELECT  Understanding the SELECT statement

SELECT 語句的目的是定義新的 Cube 空間,新的Cube 空間是由類似於 COLUMNS或者ROWS 這樣的軸組成,在這些軸上的點都是由Set里元組中的成員或者成員的組合組成的。

                    

在這個圖中,由 Calendar Year 和 Country 兩個層次結構中的成員構成了一個元組 Tuple,三個這樣的Tuple 構成了一個 SET,用這個 SET 描述了一個 COLUMNS 的軸。 這個軸其實是一個平面,是由Calendar Year 和 Country 兩個屬性層次結構形成的平面。另外的一個 SET 中,由四個 Category 成員元組形成了另外的一個 ROWS 軸。這兩個軸形成了一個兩維空間,而這個空間平面上的點都是由這兩個軸交叉的點組成的。

之前第三章我們描述這樣的交叉都是在元組Tuple 中定義的,例如像本示例提到的 構成COLUMNS 軸上的 [CY2002]和[United States] 再加上 ROWS 軸上的  [Accessories] 實際上就這一個交叉點用元組 Tuple 來表示的話就應該是:

([CY2002],[United States],[Accessories])

那么這個元組實際上還是一個局部元組,按照第三章的理解(請查看第三章我的學習筆記  http://www.cnblogs.com/biwork/archive/2013/04/09/3010199.html)

SSAS還會對這個局部元組還會對其它未能顯示列出的軸自動按照一定規則自動補齊,所以上面的示例中哪些交叉點不僅僅是這三個軸的交叉點,而且也應該包含了其它屬性層次結構作為軸時的交叉點,比如默認的 Reseller Sales 度量值緯度。

就這個例子,可以忽略這種局部元組的說法,可以認為兩個軸 [Date].[Calendar] 和 [Geography].[Country] 合起來構成了一個面,而這個面又作為一個新的軸存在並以 COLUMNS 的形式出現,[Product].[Category] 這一個屬性層次結構構成了一個單獨的軸以 ROWS 的形式出現。很自然的理解,COLUMNS 出現在查詢結果的列的位置,而 ROWS 出現在行的位置,行和列的交集就形成了各個 Tuple ,然后按照第三章的規則獲取各個Tuple 最終定位的值。

通過這個例子可以發現:

有三個屬性層次結構被顯示寫出,[Date].[Calendar] 屬性層次結構有3個成員,[Geography].[Country] 有1個成員,所以3*1 這兩個軸先構成了一個面。然后再加上 [Product].[Category] 軸有4個成員,所以 3*4 就構成了12個點,這12個點構成了一個查詢集合。

5. 帶有Where 條件的 Slicer Axis (切片軸)

書上通過兩個例子來講解其中的區別:

SELECT { ([Date].[Calendar].[CY 2002][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2003][Geography].[Country].[United States]), ([Date].[Calendar].[CY 2004][Geography].[Country].[United States]) } ON COLUMNS, { ([Product].[Category].[Accessories]), ([Product].[Category].[Bikes]), ([Product].[Category].[Clothing]), ([Product].[Category].[Components]) } ON ROWS FROM [Step-by-Step]

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, { ([Product].[Category].[Accessories]), ([Product].[Category].[Bikes]), ([Product].[Category].[Clothing]), ([Product].[Category].[Components]) } ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

從這兩個對比能夠看出他們之間相同的地方和區別:

相同的地方就是查詢結果都是一樣的。

不同的地方就是第一個查詢中,由於([Geography].[Country].[United States])是第一個 SET 中組成Tuple的一個元素,因此會作為 COLUMNS 的一部分顯示在列頭。

6. SELECT  語句中的軸

SELECT 語句最多可以支持 128 個軸,軸的序號從 0 ~ 127,但是基本上我們不會使用的到那么多,一般只使用前兩個,即我們常用的 COLUMNS 和 SETS。因為大多數客戶端工具只能支持到二維即顯示行和列。並且是使用這些軸的名稱的時候,他們的順序必須是連續的. 即如果寫了 ROWS,那么COLUMNS 也必須存在 ,不能只使用 ROWS 而不使用COLUMNS。

下圖中顯示了前5個軸的正式名稱,短名稱和別名。

這樣寫不會有問題,但是為了方便閱讀最好還是使用 COLUMNS 和 ROWS 的形式

SELECT { ([Date].[Calendar].[CY 2002],[Geography].[Country].[United States]) } ON AXIS(0), { ([Product].[Category].[Bikes]) }ON 1 FROM [Step-by-Step];

7. Members 函數的使用

Members 函數使用的頻率非常高,又沒有任何參數,使用它主要是為了從屬性層次結構或者屬性層次結構某一層中取出所有的成員。

[Dimension].[Hierarchy].Members

[Dimension].[Hierarchy].[Level].Members

如果某一個Hierarchy 層次結構沒有指定特別的Level時,Members 函數就會返回包含 ALL 以內的所有成員。如果指定了特定的Level,那么就只有這個層次結構Level 上的成員被返回。

另外要注意的是,Members 函數返回的是一個成員的集合(Set) {…},集合本身是由 Tuple 元組(..),(..)構成的,而元組里面的內容是成員[…].[…].[…].  那么在Members 返回這些成員時,會為每一個成員自動的包裝到一個一個的Tuple中,最后所有的Tuple 組成一個集合。

Members 函數查詢一示例

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, { ([Product].[Category].[Accessories]), ([Product].[Category].[Bikes]), ([Product].[Category].[Clothing]), ([Product].[Category].[Components]) } ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

在這個查詢中,ROWS 軸上引用了 Product緯度的 Category層次結構中的四個成員,看看這個結構,先把這些概念分清楚。這也是我之前一直不能理解的東西,分不清楚為什么在 Members 下面能看到 Accessories,Bikes,Clothing,Components 然后在Category 下面也看到這些東西。

Product 維度的層次結構與成員

首先看 Product,這個是緯度的名稱,通常就說做 Product 緯度。

六個方格表示的 Category 是屬性層次結構,換個空間表述它,它就是多維空間中的一個軸。在這里,我們提到的緯度中的屬性層次結構一般包含有兩個級別,第一個級別是 ALL,第二個級別是具體的成員。

ALL 的作用就是保存聚合了 Accessories,Bikes,Clothing,Components這些成員 的值,所以能看到 [All Products] 這個元素在其它四個子成員之上而位於Category hierarchy 之下。

最下面的Category 表示一個Level,這個Level 很顯然在層次結構中位於 ALL 之下,那么所有 ALL 之下的成員就歸到這個Level 中在下面一一列出來。所以這里的 Category 不能像 All Products一樣表示的是一個成員,而應該是一個Level。

了解了這些之后,我們通過以下這些例子來看看Members 函數使用的效果。

Members 函數查詢二示例

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, {  --[Product].[Category].[Category] [Product].[Category].[Category].MEMBERS } ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

這個查詢等同於 Members 函數查詢一示例,將這個引用分解下 [Product].[Category].[Category].MEMBERS

[Product 維度].[Category 層次結構].[Category Level].MEMBERS 那么對應上面的Product維度樹 Category Level 下的所有成員就是示例一中的那些成員。

也可以寫成 [Product].[Category].[Category] 默認情況下也訪問到 Category Level 下的所有成員。

更進一步看這個查詢

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, { [Product].[Category].[All Products]   --    [Product].[Category] } ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

這里的 [All Products] 指的不是 Category 下的包括 ALL 的所有成員,而是指 ALL 這一個成員。

也可以省略掉 [All Products] 而直接寫成 [Product].[Category] 因為這樣只有 維度.層次結構 的情況下默認也是訪問 ALL 這個成員,除非 ALL 這個成員被設置為隱藏不可見。

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, { [Product].[Category].MEMBERS } ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

[Product].[Category].MEMBERS  才表示包括了 ALL 這個成員的所有成員

 8. MeasureGroupMeasures 函數的使用

返回某一個 Measure 組中所有的度量值(非計算)

SELECT {[Product].[Category].Members} ON COLUMNS, {MeasureGroupMeasures("Reseller Sales")} ON ROWS FROM [Step-by-Step]

9. CrossJoin 函數

CrossJoin 函數的作用是可以讓一個Set中的所有元祖Tuple 與另外的一個Set中的所有元祖形成一個交叉組合。

語法 - Crossjoin( {Set1},{Set2} [,. . . {Setn} )

CrossJoin 里可以有兩個或者兩個以上的 SET 作為參數,並且在 SSAS 中可以使用 * 來代替 Crossjoin這個關鍵字。

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, Crossjoin( {[Product].[Category].[Category].Members},-- 1 Member Cross Join 2 Measures  { ([Measures].[Reseller Sales Amount]), ([Measures].[Reseller Order Quantity]) } ) ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

Category Level 下有四個成員 Accessories,Bikes,Clothing,Components 通過與 [Measures] 下的兩個成員 Reseller Sales Amount 和 Reseller Order Quantity 交叉連接后,其實就變成了這樣的 MDX 查詢,查詢的結果和上面的示例是一樣的。

注意這里的 Measures 也是一個維度,但這個維度比較特殊,它是度量值維度也叫事實維度,它不同於其它的維度,度量值維度是沒有 ALL 這個成員的。

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, { ([Product].[Category].[Accessories],[Measures].[Reseller Sales Amount]), ([Product].[Category].[Accessories],[Measures].[Reseller Order Quantity]), ([Product].[Category].[Bikes],[Measures].[Reseller Sales Amount]), ([Product].[Category].[Bikes],[Measures].[Reseller Order Quantity]), ([Product].[Category].[Clothing],[Measures].[Reseller Sales Amount]), ([Product].[Category].[Clothing],[Measures].[Reseller Order Quantity]), ([Product].[Category].[Components],[Measures].[Reseller Sales Amount]), ([Product].[Category].[Components],[Measures].[Reseller Order Quantity]) } ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

上面的代碼又可以回到第三章的 Partial Tuple 局部元組,理解一下它們在空間中的定位。

CROSSJOIN 也可以用 * 運算符代替,語法是 {SET1} * {SET 2} * {SET..}

SELECT { ([Date].[Calendar].[CY 2002]), ([Date].[Calendar].[CY 2003]), ([Date].[Calendar].[CY 2004]) } ON COLUMNS, {[Product].[Category].[Category].MEMBERS } -- SET 1 * { ([Measures].[Reseller Sales Amount]), ([Measures].[Reseller Order Quantity]) } -- SET 2 ON ROWS FROM [Step-by-Step] WHERE ([Geography].[Country].[United States])

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

 


免責聲明!

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



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