MDX基本概念和语法
1 MDX简介
MDX(multi-dimensional expressions多维表达式)是一种语法,支持多维对象与数据的定义和操作。
1.1 MDX重要概念
多维表达式 (MDX) 的用途是使对多个维度的数据的访问更为简单和直观。它的主要概念如下:
- 维度(Dimensions)、级别(Levels)、成员(Members)和度量值(Measures)
- 单元(Cells)、元组(Tuples)和集合(Sets)
- 轴维度和切片器维度(Axis and Slicer Dimensions)
1.2 维度(Dimensions)、级别(Levels)、成员(Members)和度量值(Measures)
这组概念只从单个维度角度理解,不涉及到维度的交集
上图中多维数据集使用了三个维度(dimensions):“时间”、“路线”和“源”,还有两个度量值:“包”和“上一次”。
-
维度(Dimensions)
对于多维数据,则可以用具有两个以上维度(Dimensions)的结构来表示。这些称作多维数据集的结构具有多个维度。 -
级别(Levels)
可以认为是对维度的细分,如维度“路线”分为“东半球”和“西半球”两个级别(levels)。 -
成员
代表维度中一次或多次数据出现的项。把维度中的成员看做基础数据库中的一个或多个记录,其该列内的值归入该分类。
成员 表示属于某个属性的实际数据值。
例如,下图中的关系图中加入阴影表示"时间.[下半年].[第三季度]"的成员。可以理解成员是某个维度级别的数据元素集合(此处集合和下面集合为不同概念)。
- 度量值
是单元格中聚合为总和、计数、百分比、最小值、最大值或平均值的数值数据值。 度量值是实时计算出的动态值,响应用户导航并与数据透视表交互。
MDX 中的重要概念 (Analysis Services)
1.3 轴维度和切片器维度
- 轴维度:SELECT语句用来选择要返回的维度和成员,称为轴维度;
- 切片器维度:WHERE语句用来将返回的数据限定为特定维度和成员条件,称为切片器维度。
轴维度预期返回多个成员的数据,而切片器维度预期返回单个成员的数据。
1.4 单元(Cell)、元组(Tuple)和集合(Set)
SQL从表返回二维数据子集,而MDX从多维数据集返回多维数据集子集。
- 单元(Cells)
所有维度共同确定的一个成员
多维数据集关系图表明多维成员的交集创建单元(Cells),从这些单元可以获取数据。为标识和析取这类数据(不管这些数据是单个单元还是多个单元块),MDX称为元组(Tuples)的参照系。
如上图中元组标识其中值为240的单元:
(源.[东半球].非洲, 时间.[下半年].[第四季度], 路线.航空, 度量值.包)
- 元组
元组列出维度和成员来标识多维数据集内的单个单元和更大的单元部分;因为各个单元是多维数据集所有维度的交集,所以元组可以唯一标识多维数据集中的每个单元。
元组可以标识多维数据集中的一部分,不必指定某个特定单元,也不必包括多维数据集中的所有维度。如一下示例均为多维数据集关系图的元组:
(源.[东半球])
(时间.[下半年],源.[西半球])
- 单元组
只有一个维度的确定的元组
时间.[下半年]
- 多元组
由多个维度共同确定的元组,需要将维度放在圆括号内,逗号隔开
(时间.[下半年], 源.[非陆地].[航空])
- 集合(Set)
元组的有序集合称为集合。在轴维度和切片器维度有这种元组集合组成.
{ (时间.[上半年], 源.非陆地.航空), (时间.[下半年], 源.非陆地.海路) }
2 基本语法
2.1 MDX 语句的基本语法:
2.1.1 MDX查询语句
语句构成:
- 语言语句(例如,SELECT、FROM、WHERE)
- OLAP维度(产品、日期或地理位置、日期层次结构)
- 度量值(销售额、库存)
- MDX函数(SUM、AVG、FILTER)
- 集合(排序的成员集合)
SELECT [axis specification] ON COLUMNS, [axis specification] ON ROWS FROM [cube name] WHERE [slicer specification]
例如:
SELECT
{[Measures].[Reseller Sales Amount],[Measures].[Internet Sales Amount]} on columns,
[Date].[Calendar Year]. Members on rows
FROM[Adventure Works]
-
COLUMNS和ROWS:两者可以调换过来,如 A on columns, B on rows 改成 A on rows, B on columns,相应的查询结果的行列也会调换过来。
-
SELECT:字句指定一个集合,把它放到轴上;
-
FROM:指定查询的cube
-
方括号“[]”:用户维度名、级别名、维度成员名,避免和函数混淆(函数名不加方括号),或者中间有空格或特殊符号
-
WHERE:指定切片,对不出现在轴上的维度成员进行限定
-
分组:没有group by字句,分组是隐含的;
-
排序:没有order by字句,排序只会对某个轴进行,使用排序函数
-
不区分大小写
-
注释:支持sql注释外,还有://和/* … */注释。
2.1.2 MDX与SQL的区别
- 维度意义的差别
SQL处理查询仅涉及到列和行两个维度,而MDX在查询中可以处理多个维度。 - 语句含义
在SQL中,SELECT语句中的列用于指定查询的列布局,而WHERE字句用于过滤返回的数据行;在MDX中,SELECT字句可用于定义几个轴维度,而WHERE字句可对查询限制特定的维度或成员。 - 创建查询过程
在SQL语言中,查询的创建者将二维行集的结构形象化并且加以定义,通过编写对一个或多个表的查询来对该结构的内容进行填充。
MDX查询的创建者通常将多维数据集的结构形象化并且加以定义,通过编写对单个多维数据集的查询来对该结构的内容进行填充。 - 查询结果集
SQL中查询结果集是行与列组成的二维表;MDX的结果集可以有多个维度,结构形象化比较困难。
2.2 核心函数
2.2.1 MEMBERS & CHILDREN
-
MEMBERS:函数返回某个维度属性下的所有成员,每个维度默认都包含一个all(全部成员),在没有指明某个具体的成员时,该属性默认返回的是这个all值。
例:State维度级别的全部成员列表。(虽然参考链接中没有关于数据的介绍,和微软MDX的文档中数据貌似是一致的)
第一行是“All Customers”,为所有客户成员值。每个维度默认都包含一个all(全部成员),在没有指明某个具体的成员时,该属性默认返回的是这个all值。- NON EMPTY
筛选掉null值,增加NON EMPTY关键字使得生成的结果更紧凑,从而使查询变得更高效。
- NON EMPTY
-
CHILDREN:返回某个维度属性下的所有成员,不返回all
2.2.2 ORDER函数
函数有三个参数:
- 要显示成员的成员集合
- 排序的度量值
- 排序顺序(倒序DESC,升序ASC)
例:如果对同一个州客户的Internet销售额进行降序排序
SELECT
{ [MEASURES].[Internet Sales Amount], [MEASURES].[Internet Gross Profit] } ON COLUMNS,
NON EMPTY ORDER ( [Customer].[State-Province].CHILDREN, [MEASURES].[Internet Sales Amount], DESC )
FROM [Adventure Works]
例:如果需要在地理维度和商品维度同时查看Internet销售额和毛利,则可以将产品类别和地区属性同时放置在行轴上。
SELECT
{ [MEASURES].[Internet Sales Amount], [MEASURES].[Internet Gross Profit] } ON COLUMNS,
NON EMPTY ( [Customer].[State-Province].Children, [Product].[Category].CHILDREN ) ON ROWS
FROM [Adventures Works]
从上图返回结果可以看到,默认的顺序是按照维度中该属性的成员默认顺序显示,即首先按Customer维度的State-province属性成员排序,然后按Product维度的Category属性成员排序。我们可以用Order函数对结果重新进行排序。
Order函数的第一个参数由于涉及两个维度的成员,可以用*连接两个维度。
SELECT
{ [MEASURES].[Internet Sales Amount], [MEASURES].[Internet Gross Profit] } ON COLUMNS,
NON EMPTY ORDER ( [Product].[Subcategory].CHILDREN*[Customer].[State-Province].CHILDREN, [MEASURES].[Internet Sales Amount], DESC ) ON ROWS
FROM [Adventure Works]
从查询结果我们可以看到,首先按Product维度的Category属性成员排序,对同一商品类别的地区,则按销售额由高往低(DESC为降序排列)显示客户所在的州。如果想对所有返回结果均按照销售额由高往低排序,则须用BDESC关键字替换DESC关键字。BDESC关键字可以将维度或层次结构的定义拆开,仅根据度量排序。
可见,MDX中隐含分组,没有group by函数
2.2.3 冒号(:)
使用冒号(:)返回属性成员中连续的几个成员值(在轴上都可以使用,不限定在rows上)
例:显示2002年2月到2002年5月之间的Internet销售额数据。
SELECT
{ [MEASURES].[Internet Sales Amount], [MEASURES].[Internet Gross Profit] } ON COLUMNS,
{ [Date].[Calendar].[Month].[June 2002]: [Date].[Calendar].[Month].[December 2002] } ON ROWS
FROM [Adventrure Works]
2.2.4 FILTER
对度量进行筛选使用FILTER(Where子句可以对结果集进行切片,即对维度成员进行筛选。)
例:要显示销售额大于10000万美元,销售毛利大于1000万美元的结果集
SELECT
{ [MEASURES].[Internet Sales Amount], [MEASURES].[Internet Gross Profit] } ON COLUMNS,
FILTER ( [Product].[Subcategory].CHILDREN, [MEASURES].[Internet Sales Amount] > 100000 AND
[MEASURES].[Internet Gross Profit] > 1000 ) ON ROWS
FROM [Adventure Works]
2.2.5 CROSSJOIN
返回一个或多个集的叉积。
函数返回同一维度中属性层次结构中的属性层次结构成员的叉积,自动共存将限制只返回那些实际存在的元组集,而不是返回整个笛卡尔乘积的元组。 所得集中元组的顺序取决于要联接的集的顺序以及其成员的顺序。
例:查询2003年和2004年在Australia、Canada、United States三个国家的Internet销售情况
SELECT
{ [MEASURES].[Internet Sales Amount], [MEASURES].[Internet Gross Profit] } ON COLUMNS,
CROSSJOIN(
{ [Date].[Calendar Year].&[2003], [Date].[Calendar Year].&[2004]},
{ [Geography].[Country].&[Australia], [Geography].[Country].&[Canada], [Geography].[Country].&[United States] }
) ON ROWS
FROM [Adventrue Works]