您的位置:首页 > 数据库

SQLServer商业智能系列:MDX基础

2011-10-25 17:58 239 查看
SQLServer商业智能系列:MDX基础
第一次使用MDX
轴的应用
MDX语法基础

【IT168 专稿】
一、什么是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所示:

表1-1
销售金额
销售数量
Q1, 2007
102,949.10
3,462
Q2, 2007
89,125.12
2,156
下面的MDX查询将从OLAP中获得表1-1的内容:

SELECT
{ [Measures].[ 销售金额], [Measures].[销售数量] }
on columns,
{ [Time].[Q1, 2007], [Time].[Q2, 2007] }
on rows
FROM [Sales]
WHERE ([Customer].[MA])

在上面的查询中,涉及到了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语句:

SELECT
{ [Time].[Q1, 2007], [Time].[Q2, 2007], [Time].[Q3, 2007] }
on columns,
{ [Customer].[MA], [Customer].[CT] }
on rows
FROM Sales
WHERE ( [Measures].[销售额] )

表1-2
Q1,2007
Q2,2007
Q3,2007
MA
96,949.10
12,688.40

104,510.20

CT
24,660.70

91,025.00

16,643.90
我们可以从上面的代码看到,时间、位置和销售业绩仅仅被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的轴上。对于没有名称的轴,必须使用索引来引用轴。我们还可以在查询中混合使用索引和名称,代码如下:



然而,一个使用轴的查询还必须使用索引为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]

学mdx语句必备基础知识
看了帮助,以下是基础知识,要看懂微软帮助的话,必须看懂如下概念,看不懂的话!别往下看!

成员、成员名和成员键、计算成员、成员函数、元组、元组函数、元组和维数、集合、聚合函数、集合和维数、命名集
成员:

成员是代表维度中一次或多次数据出现的项。请把维度中的成员看作基础数据库中的一个或多个记录,其该列内的值归入该分类。成员是描述多维数据集中的单元数据时的最低参照层次。

例如,下面的关系图加入阴影以表示"时间.[下半年].[第三季度]"成员

注意“[”和“]”

成员名和成员键:

可用其成员名或其成员键引用某个成员。上一示例中用其成员名"第四季度"引用"时间"维度中的成员。但是,在具有非唯一成员名的维度中成员名可以是"重复"的("不甚理解"),或者在可更改维度中成员名是可更改的。

引用成员的"可选方法"是引用成员键。成员键由维度用来专门标识给定成员。在 MDX 中使用"和"号 (&) 字符将成员键与成员名区别开,如下面的示例所示:

[Time].[2nd half].&[Q4]

在这种情况下,使用"第四季度"成员的成员键 Q4。引用成员键确保在可更改维度中以及在具有非唯一成员名的维度中成员的正确标识。

"和"(&) 号字符可用来表示任何 MDX 表达式中的成员键引用。

计算成员:

还可将成员创建为 MDX 查询的一部分,以使返回的数据基于评估表达式,而不是要查询的多维数据集中所存储的数据。这些成员称为计算成员,它们提供大量的 MDX 的功能和灵活性。在 MDX 查询中用 WITH 关键字定义计算成员。例如,如果想要通过增加"包"度量值现有值的 10% 来对所有包裹进行预测估算,可以仅创建一个提供此信息的计算成员,并象使用多维数据集中的任何其它成员那样使用它,如以下示例所示。

WITH MEMBER [Measures].[PackagesForecast] AS

\'[Measures].[Packages] * 1.1\'

成员函数:

MDX 提供许多函数来从其它 MDX 实体(如维度和级别)检索成员,因此对成员的显式引用并非总是必要。

Time.[1st half]等价于

Time.FirstChild

元组:

元组用于定义来自多维数据集的数据切片;它由来自一个或多个维度的单个成员的有序集合组成。元组用于标识来自多维数据集的特定多维数据块;由来自多维数据集中各个维度的一个成员组成的元组完全描述单元值。换言之,元组是一种成员向量;请把元组看作基础数据库中的一个或多个记录,其这些列内的值归入这些分类。一系列关系图给出了元组的各种类型。

“帮助中有两个图,画得很好,看看很直观!”

在 MDX 中,元组根据其复杂性依照语法进行构造。如果它仅由来自单个维度的一个成员组成(通常称作简单元组),则以下语法是可接受的。

Time.[2nd half]

如果它由来自不止一个维度的成员组成,则元组所表示的成员必须括在圆括号内,如以下示例所示。

(Time.[2nd half], Route.nonground.air)

由单个成员组成的元组也可括在圆括号内,但这不是必需的。元组常常编组成集合,以便在 MDX 查询中使用。

元组函数:

有一些返回元组的 MDX 函数,它们可在任何接受元组的地方使用。

元组和“维数”!:

元组可包括多个维度中的成员,也可包括来自同一个维度的多个成员。术语维数用来表示元组中成员所描述的维度。顺序在元组的维数中起一定作用,并可影响集合内元组的使用。

集合:

集合是零个、一个或多个元组的有序集合。集合最常用于在 MDX 查询中定义轴维度和切片器维度,并且同样可能只具有单个元组或可能在某些情况下为空。下面的示例显示具有两个元组的集合:

{ (Time.[1st half], Route.nonground.air), (Time.[2nd half], Route.nonground.sea) }

一个集合可包含同一个元组不止一次的出现。下面的集合是可接受的:

{ Time.[2nd half], Time.[2nd half] }

集合指以元组表示的一组成员组合,或指集合中的元组所代表的单元中的值,视集合使用的上下文而定。

在 MDX 语法中,元组用花括号括起来以构造集合。

重要!!! 由单个元组组成的集合不是元组;MDX 将其解释为集合。某些 MDX 函数接受元组作为参数,而如果传递单个元组集合,则会产生错误。元组和单个元组集合不可互换。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: