MDXFORSSASChapter3UnderstandingMDX项目需要用MDX,所以翻译了ProfessionalMicrosoftSQLServer2012AnalysisServiceswithMDXandDAX.pdf中第II部分第三章的内容。有翻译不当之处请联系QQ:185633513或发送EMAIL:yubinsure@gmail.com进行修正。2013余斌SUREKAM2013/8/71什么是MDX?WhatisMDX?结构化查询语言SQL是用来从关系型数据库获取数据,而多维表达式Multi-DimensionaleXpressions(MDX)是从分析服务数据中获取数据的查询语言。MDX支持两种模式:表达式语言:定义和操作分析服务器的对象和数据,用于计算。查询语言:从分析服务器获取数据。MDX微软最初于1998年SQLServerAnalysisServices7.0版本之时设计的,但它也是一门常规的、标准化的从OLAP数据库获取数据的语言。很多其它的OLAP供应商支持MDX,包括MicrostrategyIntelliganceServer,HyperionEssbaseServer,和SAS的EnterpriseBIServer。有一些供应商延续了MDX的标准,还自主开发额外的功能,但我们期待延续扩展的部分也能遵从MDX的标准。分析服务器为MDX标准化定义通过OLEDBforOLAP提供了多种扩展方式。在本书中,你将学习SQLServerAnalysisServices2012支持MDX的方式。MDX概念MDXConcepts在SQLServerAS服务上的一个多维数据库包含一个或多个cube。Cube是为了用户对多数据进行分析而设计。每一个cube必须包含两个维度(有一个叫Measures的特殊维度),但通常会包含两个以上的维度。例如,在插图3-1中显示的维度仅仅是AdventureWorks立方体中的一部分。你可以在的数据库和多维数据模型项目。在SSDT中打开AdventureWorksDW多维项目,在cube结构页签中可以看到组成cube的Measure和维度。指标和指标组MeasuresandMeasuresGroup在cube当中,Measure对象是维度的特殊表现形式。Measures是用于数据分析的定量实体。你可以在图3-1的示例工程中看到一些measures.2每一个Measure都是叫做度量组中的一部分。度量组存放相关的measure,每一个measure只能属于一个度量组。度量组主要用于在客户端工具中对measures进行导航和提高易用性。在MDX中查询度量的时候,度量组是不会被用到的。通常它们使用在某些函数中,这个将在后面的章节中进行讨论。层级结构和层HierarchiesandHierarchyLevels在AdventureWorkscube中你可以看到维度有一个或多个层级结构,并且每一个层级结构包含一个或多个层。插图3-2中展示了一个简化了的cube,它包含三个层级结构——Calendar,ProductLine,和Country——我们通过分析这些数据来阐述这一章。在AdventureWorksDW示例中,日期维度的Calendar层级结构包含5层:CalendarYear,CalendarSemester,CalendarQuarter,Month,和Date。ProductLine和Country层级结构为属性层级,只分别包含两层:AllLevel和ProductLine或Countrylevel。你将在第5章和8章中学到更多关于维度、层级结构和层。3成员Members每一个层级结构包含一个或多个被称作“成员”的项。每个一成员相当于基本要素表(维表)中被一次或多次引用到的值。插图3-3中展现了日期维度中Calendar层级的成员。在Calendar层级结构中这些项:CY2005,H1CY2005,H2CY2005,Q1CY2005,Q2CY2005Q3CY2005,andQ4CY2005都是成员。你可以看到每一层的成员包括层级结构的成员集。你也可以查询特定层上的成员。例如:Q1CY2005,Q2CY2005,Q3CY2005,andQ3CY2005是CalendarYearCY2005下的CalendarQuarter层的成员。4在MDX中,层级中的每一个成员有都唯一的名称。你可以通过维度名、层次结构名和级别名组成的名称路径(使用成员的名称)或key路径(使用成员的key)去访问一个成员。如:成员Q1CY2006在层级结构Calendar中表现为:[Date].[Calendar].[CalendarQuarter].[Q1CY2006]当名称中有空隔、存在数字、或是一个MDX关键字的时候使用方括号将名称包起来。否则,你可以省略方括号。在前面提到的维度表达式中“Date”是MDX中的关键字,因此必须使用方括号包起来。(尽管方括号是可选的,但使用它是一个很好的习惯。)对于成员Q1CY2006,以下三种表现形式都是合法的:[Date].[Calendar].[Q1CY2006](1)[Date].[Calendar].[CY2006].[H1CY2006].[Q1CY2006](2)[Date].[Calendar].[CalendarQuarter].&[2006]&[1](3)第一种,成员的格式表示为DimensionName].[HierarchyName].[MemberName]。在没有两个成员使用相同名字的时候可以这样使用。例如,如果一季度在每年中都叫Q1,那就不能使用这种格式,在MDX表达示中限制使用级别名称。如果使用前面的格式,只会返回第一个年度的Q1值。5第二种格式,你可以在导航路径中看到成员,因为你可以用这种路径中看到所有成员。最后一种使用key路径,成员的key在路径中表示为&[MemberName]。当使用key路径,成员前总是使用&符号。通常,你可以使用如下表达访问成员:[DimensionName].[HierarchyName].[LevelName].[MemberName]在本书的其它章节主要使用这种格式。在这章中用这种格式描述了Uniquename。当你查询一个指定成员的时候,我们推荐你使用服务器生成UniqueName。单元格Cells在插图3-2中展示了cube的三个面。前面的面被切分成16个方块,并且每个方块有一个数字。想象一下在每个方块中是指标[InternetSalesAmount]。如果你观察cube的其它可视面,你会发现所分析的cube中前置面里的每一个小方块实质上都是一个很小的cube。面中右上角方块包含了值1134;在其它的面也可以很好的展现这个值。这个小cube被称作cell单元格。在Cube中单元装载着所有Measures的数据值。如果Cell中的Measure值是不可用的,那相关的度量值都会是Null。在Cube中,单元Cell的数量决定于每一个度中层次结构Hierarchy的数量和每个Hierarchy中的成员数量。类似于一个三维坐标空间,每个点用X,Y,Z坐标值表示,cube中的每一个单元代表每一个维度成员。在插图3-4中,你可以看到三个维度:Product,Customer,和Date。假想下这些维度刚好有一个Hierarchy;你可以看到ProductLine有四个成员,Calendar有四个成员(仅考虑季度),Country有六个成员。因此,单元数为4*4*6=96。假设你要得到cube中阴影区的数据。销售金额在这个cell中为996。这个cell定位在Product=Mountain,Date=Quarter2,Customer=Australia的交叉位置。要得到这个数据,MDX需要唯一标识包含996的Cell。MDX查询如下:SELECTMeasures.[InternetSalesAmount]ONCOLUMNSFROM[AdventureWorks]WHERE([Date].[Calendar].[CalendarQuarter].&[2011]&[2],[Product].[ProductLine].[Mountain],[Customer].[Country].[Australia])6你能看到在这个查询中从AdventureWorkscube中基于指定的条件查询Measures.[InternetSalesAmount]的值,条件都放在where子句中用来标识单元。元组TuplesMDX表达式唯一标识的一个单元或cube的一个面被称作元组。元组通过每个维中的一个成员表示,用逗号分隔,并且用圆括号括起来。一个元组不需要明确的包含所有维度的成员。如下是基于AdventureWorks的例子:1.([Customer].[Country].[Australia])2.([Date].[Calendar].[2011].[H1CY2011].[Q1CY2011],[Customer].[Country].[Australia])3.([Date].[Calendar].[2011].[H1CY2011].[Q1CY2011],[Product].[ProductLine].[Mountain],[Customer].[Country].[Australia])1,2个元组没有包含cube中所有维度的元组。因此,它们表达了一个cube的截面。用元组表示一个cube的截面被称作切片Slice。用一个单一成员表示元组,称为简单元组,不需要用括号包起来。例如,7([Customer].[Country].[Australia])是一个简单元组,可以写成[Customer].[Country].[Australia],还可以简化成Customer.Country.Australia.如果在元组中存在一个以上的维度,通常需要用括号括起来。当你引用元组([Customer].[Country].[Australia]),实际上是引用了如插图3-4中所示了Country里Australia相关的16个单元。因此,获取此元组所指向的单元的数据,相当于获取Australia下所有客户的[InternetSalesAmount]。[InternetSalesAmount]在元组[Customer].[Country].[Australia]下的值是cube前面一个面的聚合。通过元组获取数据表达为:SELECTMeasures.[InternetSalesAmount]ONCOLUMNSFROM[AdventureWorks]WHERE([Customer].[Country].[Australia])查询结果为$9,061,000.58.元组中成员的次序没有关系,因为元组唯一标识cell,在每一个维度之间它只会有一个成员存在。集合Sets一系列元组形成的新对象称为集合Set。元组的集使用维度中完全相同集进行定义,bothintypeandnumber。在MDX查询表达式中,Set被频繁使用。Set定义在花括号内({})。Set的成员用逗号隔开。下面的例子阐述了Sets:例1:元组(Customer.Country.Australia)and(Customer.Country.Canada)来自相同的层级Customer.Country。这两个元组是一个合法的集合,表达为:{(Customer.Country.Australia),(Customer.Country.Canada)}例2:下面每一个元组有三个维度:Date,Product,和Customer。1.([Date].[Calendar].[2008].[H1CY2008].[Q1CY2008],[Product].[ProductLine].[Moun