Microsoft SQL Server 2005中的MDX指令碼功能介紹

銀河使者發表於2008-03-08
介紹
分析服務提供了一個強有力的基於伺服器的計算引擎。作為一個有效的資料表技術它事實上可以做任何事。本文件描述了Microsoft SQL Server 2005多維表示式(MDX)是如何應用到日常的業務問題中的。
本文件假設讀者已經瞭解MDX

MDX 概念
這一部份介紹了一些基本的概念。隨後的部份將會做更詳細的介紹。

立方體空間
屬性的概念相較於Microsoft SQL Server 2000有著天壤之別。在關係型資料庫中一個屬性和一個維度的關係就如同一列和一張表的關係。舉個例子,一個消費者維度可能包含諸如姓名, 電話號碼, 性別, 城市, 州等等屬性。

屬性可以通過層級結構的方式展現給使用者。在一個維度當中的屬性層級結構包括了一個可選的“全部”級別以及屬性的不同成員。舉例來說,一個消費者維度可能包 含一個由兩個級別組成的名稱屬性層級結構:“全部”級別以及一個帶有每個名稱成員的第二個級別。(父子層級結構的處理方式是不同的)

是屬性層級結構定義了立方體的空間。你可以想象一個有著多維度空間的立方體,它是由它的屬性層級結構的集合所形成的。維度是屬性層級結構的容器。一個維度 也可以包括使用者的層級結構來作為一個navigational convenience,但它們不會對立方體的空間產生影響。

一個屬性不是必須要有一個層級結構的。如果沒有建立層級結構,那麼立方體的空間就是獨立於屬性的。舉個典型的例子,一般我們不會為電話號碼屬性建立一個屬 性層級結構,原因是通常不需要通過電話號碼去檢視某個維度。如果沒有為屬性建立一個層級結構,屬性可以作為一個成員存在,而不是一個使用者層級結構中的某個 級別。

瀏覽的恆定性
單元值是完全通過它們的屬性層級結構的座標和傳遞來定義的。單元值不會因瀏覽路徑或者使用者層級結構的存在與否而改變。

舉個例子,由一個使用者層級結構 Geography定義的單元, Customer.Geography.USA.WA.Redmond.Richard,等價於由屬性層級結構 (Customer.Country.USA, Customer.State.WA, Customer.City.Redmond, Customer.Name.Richard)定義的單元.

擁有座標 (Customer.Name.Richard) 和擁有座標(Customer.Geography.USA.WA.Redmond.Richard)的單元是不一樣的. 這是因為某個屬性層級結構的一個成員並不意味著也是其它層級結構中的成員,換句話說: (Customer.Name.Richard)和 (Customer.Name.Richard, Customer.Country.All, Customer.State.All, Customer.City.All)是一樣的. 儘管消費者 Richard 住在 Redmond, WA, USA, 座標 Customer.Name.Richard 並不意味著在 City, State, 或者 Country 屬性層級結構中存在座標。

維度的葉
一個維度擁有葉。葉的含義是基於粒度屬性的-這一屬性將維度繫結到度量組。它常常是維度的鍵,但這不是必然的。例如,如果一個時間維度和一個使用日期的度量組聯絡在一起,日期就是粒度屬性,即使時間維度有著更細緻的粒度(比如,細分到分鐘)

葉是與事實表中的資料直接關聯的維度座標。一個葉是由來自屬性層級結構(其屬性或者直接或者間接的與粒度屬性相關)的成員所共同組成的,若成員是“全部” 則意味著沒有成員。例如,在一個消費者維度中包含了名稱(粒度屬性),電子郵件,城市,州,以及國家屬性,以下的維度座標就是一個葉:
(Customer.Name.Name.Richard,
Customer.Email.Email.richard@Adventureworks.com,
Customer.City.City.Sammamish, Customer.State.State.WA,
Customer.Country.Country.USA)
然而,下面的維度座標並不是一個葉,因為電子郵件屬性層級結構中的成員是“全部”級別
(Customer.Name.Name.Richard, Customer.Email.[(All)].[All],
Customer.City.City.Sammamish, Customer.State.State.Wa,
Customer.Country.Country.USA)
如果粒度屬性不是維度的鍵屬性,葉就包括了與粒度屬性無關的屬性的“全部”成員。例如,如果消費者維度的粒度屬性是城市屬性,以下的維度座標就是一個葉:
(Customer.Name.[(All)].[All], Customer.Email.[(All)].[All],
Customer.City.City.Sammamish, Customer.State.State.Wa,
Customer.Country.Country.USA)
注意    在單元中可能沒有資料是同與粒度屬性無關的屬性的成員相交的。例如,如果粒度屬性是城市,然後限定在一個名稱屬性的成員上生成空的單元。實際的行為是由在度量組上的IgnoreUnrelatedDimensions屬性來決定的。

通過定義,每個粒度屬性成員只有一個單葉。

Autoexists
立方體的真實空間是比它的屬性層級所產生的更受限制的。有一些單元是無法存在的,原因是來自同一維度的Autoexists屬性成員不能彼此並存,不能存在於這個立方體空間內。例如,(北京,加拿大)不能存在。在本文中Autoexists的概念貫徹始終。

注意     對在事實表中的資料什麼也不用做。這僅僅是一個維度的概念- Autoexists僅僅屬於在同一維度中的屬性
可以對在立方體空間中無法存在的單元發出查詢請求。例如,在語句select customer.gender.members on 0, {Customer.Name.Fred, Customer.Name.Jane} on 1 from sales中包括了在這個空間中無法存在的單元。這些單元總是空的——它們無法包含計算並且它們無法寫入。

Autoexists 在查詢結果中扮演了重要的角色:
•        當使用常見維度的集被投射到相同的軸時,被保留的成員可以彼此並存
例如:
Select crossjoin({Customer.Country.Country.USA}, Customer.States.States.members) on 0 from Sales
結果:只有那些在美國的州可以從Customer.States.States.members中保留下來.
•        每一個層級結構的“全部”成員可以自動和在同一維度中的所有層級結構的所有其它成員並存

子立方體
一個子立方體是一個交叉聯接集的集合,它將隨後的語句的空間限制到子空間。子立方體經常被引用,並且一個有效的子立方體所使用的格式有一些限制。在子立方體定義中的每個集可以是:
•        來自於一個屬性層級的除了“全部”成員以外的成員的任意組合
•        一個層級結構的單個成員或者解析到一個單個成員的一個MDX表示式
•        在一個自然層級結構的一個指定級別的成員的任意組合。
注意     一個自然層級結構是由一組屬性組成的,這些屬性中的每一個都是它下面屬性的一個成員。例如,如果城市是名稱的一個成員屬性,州是城市的;國家是州 的。地理層級結構,國家,州,城市,名稱就是一個自然層級。層級結構性別-年齡不是一個自然層級結構,原因是性別不是年齡的一個成員屬性
•        一個成員的位於多個級別的後代(僅對自然層級而言)
•        一個層級結構的“全部”成員
•        一個層級結構的葉成員
自變數“*”可以為子立方體的定義所接受。這代表了立方體的整個內容——來自每個層級結構的每個維度的每個成員

軸層級結構性
在一個查詢中存在著如何將來自於同個層級結構的成員投射到不同的軸上的規則:
•        對於沿著任何軸使用通用維度但是不同的層級結構性的投射集而言不存在限制
•        使用相同層級結構性的集不能被包含在超過一個以上的軸中
注意      一個物件的層級結構性代表了在物件中呈現的層級結構

哪種方式是向上?
在SQL Server 2000分析服務中,資料從一個級別到一個級別的聚合。例如,在一個消費者維度國家,州,城市以及名稱中,資料從名稱到城市,然後到州,再到國家的進行聚 合。如果一個計算更改了對應雷蒙德的值(但不是針對單個的消費者),在雷蒙德之上的值將會反映這一更改;也就是說對應華盛頓,美國的值,以及全部消費者成 員將會受到影響。

在SQL Server 2005中資料聚合的方式很相似但有些微的差別,原因是一個立方體可能除了屬性層級結構之外不包含任何層級結構。換句話講,如果沒有層級結構定義了“向 上”是什麼含義,資料是怎樣“向上”聚合的?如果消費者維度包含了不少的屬性並且沒有使用者定義的層級結構,什麼從什麼聚合呢?

如果有人使用屬性粒度重新檢查了立方體空間,這個問題就可以回答了。在一個立方體中的每個單元都有一個對應到某個屬性層級結構的粒度;單元或者位於屬性 “全部”級別或者位於屬性級別(在使用父子層級結構時情況可能某種程度上要更復雜一些,但原則是同樣的)。一個屬性層級結構的“全部”級別擁有一個比屬性 層級結構級別更高的粒度。例如,成員Customer.City.[All]比Customer.City.Seattle擁有更高的粒度。

一旦我們接受了每個單元都有一個粒度的事實,我們就可以使用粒度來定義“向上”的含義:
•        如果一個單元在所有屬性上有著同樣的粒度那麼它就和其它的單元有著同樣的粒度
•        如果至少一個屬性有一個更高的粒度並且其它屬性都是同樣或者更高的粒度的話,那麼這個單元就比其它的有著更高的粒度

特別注意   在其它單元之上或之下的單元可以用比較的方式來描述。沒有在其它單元之上或之下的單元被當作是不可比的;如果某些屬性處於一個更高的粒度而其它屬性的粒 度要低一些也是不可比單元。例如,通過元組(Customer.City.[All], Customer.Customer.Richard)定義的單元與單元(Customer.City.Sammamish, Customer.Customer.[All])是不可比的,原因是一個屬性的粒度高而其它的低。

現在我們有了方向感,我們可以確定資料如何聚合:資料從低向高的粒度進行聚合
這是有幫助的,但還遠沒有完。怎樣在一個立方體中間來插入一個計算來影響立方體進行聚合的方式?一元運算子?傳遞?在接下來的部份就會對此進行討論。

MDX 指令碼
一個MDX指令碼是一個命令的集合,其中的每一個通過一個分號隔開。指令碼是用來生成一個使用計算的立方體的。
這部份描述了在MDX指令碼後面的一些關鍵概念以及一些對常見的計算有所幫助的新功能

執行對宣告
指令碼看上去象一個程式一樣執行。事實上,同樣的概念在分析服務2000中已經使用了(比如傳遞以及解析順序)但是被放到了一個不為注意的位置。MDX的指令碼並不真正的“執行”。它是一套總是有效的被宣告的命令。立方體的內容總是和指令碼一致。

傳遞
在傳遞0,立方體僅僅包含事實和寫回的資料。指令碼產生傳遞 0以後的資料。
每一個指令碼中的賦值,凍結以及計算語句都產生一個新的傳遞
計算成員存在於所有的傳遞中而無論其建立在哪個傳遞中。

沒有指令碼
如果沒有定義指令碼,立方體採用一個預設的使用單命令計算的隱性指令碼。
如果指令碼存在但是空白的,一個空白的指令碼會使用但什麼也不計算。

建立計算
一個簡單的定義一個計算單元的方法是:
= ;
示例:
(Sales,Budget) = (Sales,Actual) * 1.2;
Sales = Sales *1.2 ;
每個賦值建立了它自身的傳遞,用來阻止無限遞迴。
當某個表示式引起無限遞迴時,來自前面的傳遞值被採用。例如:
Sales = Sales * 1.2
等價於
Sales = CalculationPassValue(Sales, -1, RELATIVE) * 1.2
對傳遞的明確參照是允許的但不推薦,原因是當指令碼更改時傳遞號也會更改。
計算在一個更高的粒度更改結果——確切是如何的在後面討論。

範圍
一個範圍限定對應一個子立方體的語句。如果沒有指定的範圍,預設的範圍是整個的立方體。
BNF
Scope();

...
End Scope;
:== refer to the definition of a subcube
範圍的定義是靜態的。例如,設想一個帶有一個消費者維度的立方體扮演了兩個角色: SoldTo 和 PurchasedFrom。為了定義一個關於誰將產品賣給了消費者的子立方體,下面的方法不會象預料的那樣工作:
Scope (SoldTo.Name.Name.members);
   Scope(LinkMember(SoldTo.Name.CurrentMember, PurchasedFrom.Name));
      ...
   End Scope;
End Scope;
它之所以不工作是因為定義第二個範圍的語句沒有在每一單元中重新評估;表示式SoldTo.Name.CurrentMember在原始的範圍上不是動態的


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12921506/viewspace-201765/,如需轉載,請註明出處,否則將追究法律責任。

相關文章