MDX查詢基礎(一)
本文完全轉載自:http://blog.sina.com.cn/s/blog_622a0069010120pc.htmlhttp://blog.sina.com.cn/s/blog_622a0069010120pc.html
自己初學收藏!
一、什麼是MDX
MDX是一種和SQL類似的語言,它也可以用於查詢、計算和定義一些元資料。只不過SQL是基於OLTP的,而MDX是基於OLAP的,也就是說,MDX是對多維資料進行查詢的。和其它的OLAP語言不同,MDX並不完全是一種報告形式語言。但用MDX查詢出來的結果仍然可以在客戶端程式中以表格形式進行展現。MDX和SQL一樣,也有很多不同功能的API來支援MDX。其中包括物件連結和為線上分析處理的內嵌資料功能(也就是OLE DB for OLAP)、ADO MD、ADOMD.Net、XMLA(XML for Analysis)等。OLE DB for OLAP的規範描述了MDX查詢和將被查詢資訊傳送給客戶端的資料結構之間的完整關係。
二、第一次使用MDX
在本節中,我們將按著步驟來執行一系列簡單的MDX查詢。通過對本節的學習,讀者可以很輕鬆地將MDX的概念轉化為實際的例子。
我們可以想象有一個非常簡單的立方體,這個立方體有三個維度,分別代表時間、地理位置和銷售業績。我們給這個立方體起名為Sales。現在讓我們看看下面的一個表格。這個表格中的資料是在2007年頭兩個季度在北京的銷售量和銷售額。這個表格有兩個維度,就象一個電子表格一樣,但是在第一列表示了兩個維度,因此,這個表格實際上是三個維度。表格如表1-1所示:
在上面的查詢中,涉及到了SELECT、FROM和WHERE關鍵字,這些關鍵字代表了不同的部分。MDX查詢的結果本身是一個表格,實際上是另外一個立方體。我們將要查詢的維度作為結果集的列。這個查詢應用了兩個被命名的行和列。在MDX技術中,一個軸是一個邊或一個查詢結果集的維度。使用軸要比直接使用立方體體的維度更簡單,而且每個軸還可以是多個立方體維度的組合。我們可以根據上面的語句將這個例子泛化。現在讓我們將這個查詢分成以下幾部分:
1. SELECT子句是MDX語句的開始,用於指定我們想要獲得什麼資訊。
2. ON關鍵字後面跟著用於指定維度的軸的名稱。在這個例子中將銷售業績放到columns軸上,將時間資訊放到row軸上。
3. MDX使用上卷括號{和}來裝入從一個特定的維度或維度集合中裝入資料。在我們的例子中在每個查詢中只有一個維度。我們可以使用逗號來分割不同的元素。元素名可以放到[]中,可以使用多個“.”進行分割。
4. 在一個MDX查詢中,我們指定了維度如何從我們的資料庫中對映到我們的結果集軸上。在這個查詢中是銷售業績對映在了columns軸上,而時間對映在了rows軸上。每一個查詢可以用不同數量的結果集軸。前三個軸的名為"columns","rows"和"pages",這些軸從形式上和報表的格式一致。
5. 一個MDX查詢中的FROM子句用於指定被查詢的資料的名稱。這和SQL語句中的FROM子句類似。
6. WHERE子句提供了一種用於指定在當前立方體中未出現維度的方法。如果我們不指定其它的維度,那麼MDX將使用預設的維度。因此,WHERE子句對於MDX查詢是可選的。
一但資料庫已經確定了查詢結果集的單元格,就會將從立方體中查詢出來的資料這些單元格。MDX和SQL都擁有SELECT、FROM和WHERE關鍵字。但要注意的是,這三個關鍵字和SQL中的並不一樣,在學習MDX時最好忘記SQL中的這幾個關鍵字。這是因為它們的含義和語法不相同,如果試著將SQL中的這些關鍵字的經驗應用到MDX中,是非常不明智的。下面讓我們來看另外一個例子。為了產生表1-2的結果集,我們可以寫如下的MDX語句:
我們可以從上面的程式碼看到,時間、位置和銷售業績僅僅被columns上的時間列表、rows上的客戶和WHERE部分的銷售業績選擇。
三、軸的應用
我們有很想通過“on columns/rows/”等語法將很多成員放到columns或rows或是查詢結果集的其他軸裡。對於軸的表示可以通過指定軸的名稱,如下面的MDX表示式:
SELECT
{[Customer].[MA], [Customer].[CT] }
on rows,
{ [Time].[Q1, 2005], [Time].[Q2, 2005], [Time].[Q3, 2005] }
on columns
FROM Sales
WHERE ( [Measures].[Dollar Sales] )
我們還可以使用數字索引來引用查詢中的軸,程式碼如下:
{ [Time].[Q1, 2005], [Time].[Q2, 2005], [Time].[Q3, 2005] }
on axis(0),
{[Customer].[MA], [Customer].[CT] }
on axis(1)
axis(n)的表達形式確定這些成員將被放到序號為n的輛上。對於沒有名稱的軸,必須使用索引來引用軸。我們還可以在查詢中混合使用索引和名稱,程式碼如下:
SELECT
{[Customer].[MA], [Customer].[CT] }
on rows,
{ [Time].[Q1, 2005], [Time].[Q2, 2005], [Time].[Q3, 2005] }
on axis(0)
FROM Sales
WHERE ( [Measures].[Dollar Sales] )
然而,一個使用軸的查詢還必須使用索引為0的軸,並且一個使用軸2的查詢必須使用軸1和0。否則將會出現錯誤。如以下的程式碼將丟擲一個錯誤:
SELECT
{[Customer].[MA], [Customer].[CT] }
on axis(2),
{ [Time].[Q1, 2005], [Time].[Q2, 2005], [Time].[Q3, 2005] }
on axis(0)
FROM Sales
WHERE ( [Measures].[Dollar Sales] )
四、MDX語法基礎
在這一節讓我們學習一下MDX頻繁使用的一些操作符和函式。我們將介紹它們,並描述它們常用的使用方法。下面是本節將介紹的內容。
1.逗號(,) and 冒號 (:)
2..Members
3..Children和 Descendants()
逗號(,) and 冒號 (:)
到現在為此我們已經看到逗號操作符被應用到了Mdx語句中;現在讓我們學習更多的
關於逗號的知識。首先我們可以使用逗號來分割元件和它的屬性。如下面的程式碼如示:
{ [Time].[January 2007], [Time].[February 2007],
[Time].[March 2007] }
上面語句的功能是列出2007年頭三個月資料。
在每一個維度的第一層的成員通常按著一個順序排列(通常是按著key或是名稱進行排列)。根據這個順序,我們可以將兩個成員中間的資料作為一個集合列出。而集合的兩端就是兩個成員。這兩個成員使用冒號(:)分割。這有些和在Excel中指定單元格之間的範圍類似。如下面的查詢的結果是列出2005年9月和2007所10月的月份以及在產生目錄中從Tools到Audio的資料。程式碼如下:
SELECT
{ [Time].[Sep,2005] : [Time].[Oct,2007] } on columns,
{ [Product].[Tools] : [Product].[Home Audio] } on rows
FROM [Sales]
WHERE ([Customer].[Lubbock, TX], [Measures].[Unit Sales])
我們還可以將逗號和冒號混合使用,如下面的程式碼如下:
{ [Time].[2005], { [Time].[January-2006] : [Time].[March-2006] } }
上面的程式碼建立一個2005年的集合以及2006年1月至3月的集合。
.Members
獲得一個維度、層次的成員集合是非常普遍的一種操作,也是進一步做其他操作的基礎。.Members操作符可以操作一個維度、層次,並返回所有和這些元資料範圍的所有成員的集合。如[Customer].Members返回所有的的Customer集合,而[Product].[Product Category].Members返回所有的成員的產品目錄的成員。例子程式碼如下:
SELECT
{ [Scenario].Members } on columns,
{ [Store].Members } on rows
FROM Budgeting
當一個客戶使用.Members(或是其他可以返回和響應的成員集合的元資料函式),分析服務和Essbase都不會包括任何被計算過的成員。在分析服務中還提供了AddCalculatedMembers()和.AddMembers函式來向集合中加入成員。
.Children
另一種使用頻率非常高的選擇方法就是獲得成員的孩子(children)。我們可以使用下鑽的操作,或者是簡單地獲得一個基於parent的成員的範圍。MDX提供了一個.Children函式,這個函式將為我們實現這個功能。下面的MDX語句將在rows上選擇[Product].[Tools]的成員和它的Children,程式碼如下:
SELECT
{ [Time].[Q3, 2005].Children }
on columns,
{ [Product].[Tools], [Product].[Tools].Children }
on rows
FROM Sales
WHERE ([Customer].[TX], [Measures].[Unit Sales])
我們可以通過這個函式獲得任何一個有Children的成員的Children。如果我們獲得一個葉子節點的孩子,就會得到一個空的集合。
使用Descendants()函式獲得成員的子孫
為了獲得成員的更深層次的孩子。或是為了進行更深的搜尋,我們可以使用Descendants()函式。由於這個函式的選擇過我,因此,我們只討論一下它的基本的用法。
Descendants ()方法的語法如下:
Descendants (member [, [ level ] [, flag]] )
Descendants()方法返回了和層次或當前的成員的子孫。下面是這個方法的一些選項:
SELF
BEFORE
AFTER
SELF_AND_BEFORE
SELF_AND_AFTER
SELF_BEFORE_AFTER
LEAVES
SELF僅僅引用了層的成員,這是最學用的選項。如下面的程式碼選擇了2007年的月份。程式碼如下:
SELECT
{ [Product].[Tools], [Product].[Toys] } ON COLUMNS,
Descendants (
[Time].[2007],
[Time].[Month],
SELF
)
ON ROWS
FROM Sales
WHERE [Measures].[Dollar Sales]
由於SELF使用非常頻繁,因此,這個選項是預設的。如果我們在程式碼中忽略了這個標誌。如Descendants ([Time].[2007], [Time].[Month])同樣返回2007年的月份列表。
另外一個選項SELF_AND_BEFORE表示返回SELF和“before”層之間的所有成員。如下面的程式碼挑出了在2007年的四個季度和每個月份。程式碼如下:
{ [Product].[Tools], [Product].[Toys] } ON COLUMNS,
Descendants (
[Time].[2007],
[Time].[Month],
SELF_AND_BEFORE
)
ON ROWS
FROM Sales
WHERE [Measures].[Dollar Sales]