MDX使用遇到的坑

##############mondrain
四个manager
 Session Manager:最为重要的一个部分。接受MDX查询、解析MDX,返回结果。
 Schema Manager:与初始化紧密相关。主要是一些重要的数据结构如缓存池的构建以及多维模型的生成。
 Aggregate Manager:实现了对聚集表的管理。主要是对OLAP缓存的管理,属于性能优化的部分。
 Dimension Manager:维度的管理。实现多维模型中维度和关系数据库表中列的映射,在Schema Manager也有部分功能处理这些映射。

################schema数据类型
datatype有string,Integer,Numberic,Boolean,Date,Timestamp等。

############MDX
MDX查询:多维模型的查询语言MDX(MDX是微软发布的多维查询语言标准),它的语法与SQL有很多相似之处:
select {[Measures].[Salary]} on columns, {[Employee].[employeeId].members} on rows from CubeTest
对于这条语句,COLUMNS 和 ROWS都代表查询轴,其中COLUMNS代表列轴,ROWS代表行轴。COLUMNS又可以写成0,ROWS又可以写成1,
当只有两个查询轴时,可以理解为结果的展现格式是一个平坦二维表。
这条语句的含义就是查询名字为CubeTest的立方体,列显示Measures维度的salary,行显示 Employee维度employeeId级别的所有成员,
那么得出的结果就是employeeId所有成员的salary,也就是所有员工的薪酬。


#######################mondrain schema4.0
1.元素<physicalShema>必须要有:指定cube涉及到设事实表和维表的key和关联关系,
但是physicalSchema下面的table必须要:指定cube需要的事实表和维度表,
link不是必须,可由<Dimension>下面的<Join>属性,<MeasureGroups>下面的<DimensionLinks>下面的<ForeignKeyLink>代替。

2.<Dimension>下面的<Join>属性也不是必须要有:指定雪花模型的维度表之间的关联关系。可在<physicalSchema>下的<link>中指定维表之间的关联关系。

3.<MeasureGroups>下面的<DimensionLinks>下面的<ForeignKeyLink>必须要有:指定事实表里面的measures(度量)和维表之间的关联关系。也就是事实表和维度表之间的关联关系。

4.<View>(3.0)和<Query>(4.0)的区别
  <Query>和<View>功能上一样,但是Query的语法和官网上有点区别,推荐用View。
5.visualCube(3.0?)

6.aggregateTable


################member property
在shcema中是由attribute下面的property定义的

<Attribute name="City" keyColumn="city_id">
    <Property attribute="Country"/>
    <Property attribute="State"/>
    <Property attribute="City Population" name="Population"/>
</Attribute>


SELECT {[Measures].[Store Sales]} ON COLUMNS,
  TopCount(
    Filter(
      [Customer].[City].Members,
      [Customer].[City].CurrentMember.Properties("Population") < 10000),
    10,
    [Measures].[Store Sales]) ON ROWS
FROM [Sales]

################filter函数
返回根据搜索条件对集合进行筛选所得到的集合
一般是对维度进行筛选,筛选条件是度量。

#####################成员函数
#######Cousin函数
返回与指定的子成员在父成员下方具有相同相对位置的子成员
Cousin(Member_Expresion, Ancestor_Member_Expression)
Member_Expresion:子成员的有效多维表达式
Ancestor_Member_Expression:祖先成员的有效多维表达式

注意:此函数按各级别内部的成员的顺序和位置进行操作


##################CurrentMember
返回遍历过程中指定层次结构的当前成员

Hierarchy_Expression:层次结构的有效多维表达式

注意:遍历一组层次结构成员时,在遍历过程的每一步,所操作的成员就是当前成员。
      CurrentMember函数返回该成员。

如果维度中只包含一个可见的层次结构,则可以通过此维度的名称或此层次结构的名称引用此层次结构
原因是次维度的名称会解析为它唯一可见的层次结构。
例如,Measures.CurrentMember解析为Measures维度中唯一的层次结构。


##########对维度和度量自身单条件过滤(多条件就是嵌套)
WITH
SET [~COLUMNS] AS
    {[product].[productinfo].[proTypeName].Members}
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY filter([~COLUMNS],[product].[productinfo].[proTypeName].CurrentMember.name='电器') ON COLUMNS,
NON EMPTY filter([~ROWS],[customer].[gender].[gender].CurrentMember.name='F') ON ROWS
FROM [saleinfo]

WITH
SET [~ROWS] AS
    Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}})
SELECT
NON EMPTY {[Measures].[unitprice]} ON COLUMNS,
NON EMPTY filter([~ROWS],[Measures].[unitprice]>200) ON ROWS
FROM [saleinfo]

###############行列互换,行度量互换,列度量互换
#####列度量互换
WITH
SET [~COLUMNS] AS
    Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}})
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[unitprice], [Measures].[total_cost], [Measures].[number]}) ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [saleinfo]

WITH
SET [~COLUMNS] AS
    Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}})
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY CrossJoin({[Measures].[unitprice], [Measures].[total_cost], [Measures].[number]}, [~COLUMNS]) ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS

##########行度量转换
WITH
SET [~COLUMNS] AS
    Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}})
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY [~COLUMNS] ON COLUMNS,
NON EMPTY CrossJoin({[Measures].[unitprice], [Measures].[number], [Measures].[total_cost]}, [~ROWS]) ON ROWS
FROM [saleinfo]

######行列转换
WITH
SET [~COLUMNS] AS
    Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}})
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY  [~ROWS] ON COLUMNS,
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[unitprice], [Measures].[number], [Measures].[total_cost]}) ON ROWS
FROM [saleinfo]
FROM [saleinfo]


##########TOPCount和bottomCount
WITH
SET [~COLUMNS] AS
    TopCount(Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}}), 1, [Measures].[unitprice])
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[unitprice], [Measures].[number], [Measures].[total_cost]}) ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [saleinfo]

WITH
SET [~COLUMNS] AS
    BottomCount(Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}}), 10, [Measures].[unitprice])
SET [~ROWS] AS
    {[customer].[gender].[gender].Members}
SELECT
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[unitprice], [Measures].[number], [Measures].[total_cost]}) ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [saleinfo]


##########过滤函数filter
WITH
SET [~COLUMNS] AS
    Filter(Hierarchize({{[product].[productinfo].[proTypeName].Members}, {[product].[productinfo].[proName].Members}}), ([Measures].[total_cost] > 1500))
SET [~ROWS] AS
    Filter({[customer].[gender].[gender].Members}, ([customer].[gender].[gender].CurrentMember.name = "F"))
SELECT
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[number], [Measures].[unitprice], [Measures].[total_cost]}) ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [saleinfo]

######元组的特性
元组内不能包含来自同一个维度的多个成员
一个元组的集合对等于元组

######轴维度特性
轴维度上只能接受集合<Set>,如果是手工指定成员集合,必须用{}包围,
如果使用MDX集合函数,则不需要用{}包围,因为函数返回值为集合

#######切片器维度特性
切片器维度只可接受评估为单个元组的MDX表达式


###计算成员特性
1. 计算成员可以再层次结构的任意位置创建。
2. 不仅可以创建取决于多维数据集中的现有从成员,还可以取决于同一个MDX表达式定义的其他计算成员的计算成员。
当然,只能在后面的计算成员中使用前面的计算成员,不能反过来。
WITH
    MEMBER [product].[Beer and Wine].[BigSeller]  AS
    IIf([product].[Beer and Wine]> 100,"YES","NO")
SELECT 
{[product].[BigSeller]} ON COLUMNS,
{store.[Store Name].Members} ON ROWS
From sales

##############成员函数
######Cousin函数
返回父成员下方与指定成员具有相同的相对位置的子成员

如:Cousin([1996].March,[1994])返回[1994].March

如果1996级别包含January,February,March,April,May,June,July,August,September,October,November,December成员。而1994级别包含
[1st Quarter],[2nd Quarter],[3rd Quarter],[4th Quarter],返回的是[1994].[3rd Quarter],因为相对位置一样(第三)


######Lead函数
返回成员处在其所在的维度中指定的成员后指定的位数上


成员在维度中的位置由维度的自然顺序决定,位置的编号以零为基础。
Member.Lead(index),如果index为0,则返回Member,如果index为负数,则返回前一个成员,整数为后一个成员。
Lead(1)等价于nextMember, Lead(-1)等价于PrevMember

[1994].November.Lead(3) 返回[1995].[February]

#############集合函数
##############bottomcount,topCount
BottomCount(Set,Count,Expression)第三个参数可选
从集合底部开始返回指定数目的项,可以选择首先对集合排序。

同理对应topCount

#############bottomPercent,topPrecent
对集合排序并返回指定数目的最底层的元素,这些元素累计合计至少未指定的百分比。
BottomPercent(Set,Count,Expression)第三个参数可选


######Distinct,Except
从尾部删除重复元组
Distinct({(a,b),(c,d),(a,b)}) 返回{(a,b),(c,d)}

查找第一个集合中与第二个集合的不同的项,可以选择保留第一个集合中的重复项
Except(Set1,Set2,ALL)第三个参数可选


############Filter函数
返回根据搜索条件指定集合进行筛选所得到的集合

Filter(Set,Search Condition)  等价于 IIF(Search Condition, Member, NULL)


##############Head函数
返回集合中指定数目的前若干个元素
Head(Set,Expression) Expression默认为1,如果小于1,返回空集合,超出了集合中元组的个数,返回原始集合。

#############Hierarchies函数
在层次结构中对集合的成员排序

Hierarchize(Set,Post) 第二个参数可选,返回集合始终保留重复项
没指定排序条件时,级别中的成员按照其自然顺序排序,指定Post关键字后,采用后续排列。

############Intersect
返回两个输入集合的交集,可以选择保留重复项
Intersect(Set1,Set2,ALL) 第三个参数可选

根据默认设置,在相交之前先删除两个集合中的重复项。

###########nonEmptyCrossjoin
以一个集合的形式返回两个或者多个集合的矢量积,不包括空元祖以及无相关事实数据的元组。

NonEmptyCrossjoin(Set1,Set2,Set3,Crossjoin set count)  第三和第四个参数可选

#################Order
排列指定集合的成员,可以选择保留或打破层次结构

Order(Set,Expression,ASC|DESC|BASC|BDESC)

order有两种变化形式,按层次结构排序(ASC或DBSC)和不按层次结构排序(BAS和BDESC)
按层次结构进行排序首先按成员在层次中的位置对其进行排序,然后再对每个级别进行排序。
不按层次结构进行排序在对集合中的成员排序时,不考虑层次结构。
没有明确说明是默认使用ASC


########union
返回对两个集合进行Union运算生成的集合,可以保留重复的成员

Union(Set1,Set2,ALL) 第三个参数可选
ALL标志表示在并集中保留重复项,从尾部删除重复项。

################逻辑函数
###IsEmpty()
如果表达式的值为空,则返回TRUE,否则返回FALSE

IsEmpty(Expression)


##########And
逻辑与

Logic Expression AND Logic Expression


#########or
逻辑或
Logic Expression or Logic Expression

############Xor
逻辑异或

Logic Expression Xor Logic Expression

############ >, >=  , <=, <, <>, =
比较大小

两版本:Logic Expression 符号 Logic Expression
        String   符号   String
        
        
##########数值函数

#########Aggregate
返回根据成员的聚合类型,用适当的聚合函数计算所得到的值
Aggregate(Set,Numberic Expression)

########Avg
返回某一集合上对数值表达式求得的平均值

Avg(Set,numeric Expression)


############count
返回集合中项目的数目(具体数目取决于集合)
维度:Dimensions.count
级别:Dimensions|Hierarchy.levels.count
集合:1.count(set,EcludeEmpty|includeEmpty) 参数而用来标志排除或者包含空单元
      2.Set.count   包括空单元
      
########Max,Median,min,sum
返回在某一集合上对数值表达式求得的最大值。
Max(Set,Numeric Expression) 第二个参数可选
 
median同理,求中位数
min求最小
sum求和

#########Value
返回度量值得值
Member.Value
度量值的默认属性

#########Name
返回对象名称
Dimension.Name
Level.Name
Member.Name
Hierarchy.Name

#######UniqueName
返回对象的唯一名称


###########Properties
返回包含成员属性值得字符串

Member.propertied('String Expression')


######||
将两个字符串连接起来
String Expression || String Expression

###########标量表达式
包含字符串表达式,数值表达式,日期表达式
一般用在计算成员中使用

##########NON EMpty
删除查询中的空行和空列


#########空值处理
与数值一起运算时,做0处理
与字符串运算时做空字符串处理
与数值排序时,排在与0相同的位置,与0排序时在零前面
与字符串排序时,排在与空字符串相同的位置,与空字符串排序时,在空字符串前面

######where子句特性
后面接元组和集合,没有所谓的SQL中的or和and操作,只有立方体的切片条件
如果where子句没有显示指定的话,这默认为剩下维度的所有级别

############filter函数特性
fliter不支持对度量本身进行过滤,且跟行列位置没有关系,不管过滤条件是维度信息还是度量信息,但是不会报错,只是数据不对或返回空
不支持过滤后的结果用于两维度不放在同一个行轴或列轴的cross join或者对crossjoin后的结果进行过滤

SELECT
NON EMPTY {[Measures].[number],[measures].[unitprice],[measures].[total_cost]} ON COLUMNS,
NON EMPTY filter(filter(crossjoin(Hierarchize({[product].[productinfo].[proTypeName].members,[product].[productinfo].[proName].Members}),[customer].[gender].members),[measures].[total_cost]>980),[customer].[gender].currentmember.name='M')ON ROWS
FROM [saleinfo]

注意:等同于HAVING子句,但是这个版本的好像不支持

############Attribute和Properties
在schema中用Attribute定义了成员属性,在MDX中使用properties关键字使用成员属性

Properties返回指定成员的指定属性的值,


###########元组和集合
元组的不能包含一个维度的多个成员,且成员顺序不重要
集合中可以包含重复的元组


###########单表建立cube
单表建cube(预) :MDX定义多维数据集必须至少包含两个维度,其中一个是度量值的特殊维度
但是一张表建cube不是不可行的,因为最少也需要两张表,因为数据立方体天然的就是涉及维度的概念,需要同时包含维度和度量值。
根据只要具有不同的别名,schema支持同一张表可以在不同的层次结构中使用的原理,可以将一张表在physicalSchema中定义两次,别名不一样。就可以折中的解决单表建cube的问题。


#############排序排名
TopCount,BottomCount,TopPersent,BottomPercent,Rank
使用TopCount时,维度后面必须要跟.ALLMEMBERS,如果是.MEMBERS的话会报mysql语法错误,错误如下:
check the manual that corresponds to your MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=7' at line 
暂时还不知道错在哪里,估计是bug。因为BottomCount没有这个问题。
另外,需要了解排名排序的底层怎么实现的,mysql日志中并没有执行记录。
且在排名排序函数中如果有Hierarchize函数的话数据会不对

SELECT 
NON EMPTY {[measures].[unitprice],[measures].[number]} on columns,
NON EMPTY topcount([product].[productinfo].[proName].ALLMEMBERS, 7 ,[measures].[unitprice]) on rows
FROM [saleinfo]


#########同环比
同比
WITH
SET [~ROWS] AS
    Hierarchize({[sale_month].[dateinfo].[year].Members,[sale_month].[dateinfo].[month].Members})
    
MEMBER [measures].[Change Amount Rate] AS IIF(ISEMPTY([sale_month].[dateinfo].[month].CurrentMember.parent.PrevMember),0,[Measures].[saleAmount]/([Measures].[saleAmount], Cousin([sale_month].[dateinfo].[month].CurrentMember, [sale_month].[dateinfo].[month].CurrentMember.parent.PrevMember))-1),FORMAT_STRING = '0.00%' 
SELECT
NON EMPTY {[Measures].[saleAmount],[measures].[Change Amount Rate]} ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [sale_month]

环比
WITH
SET [~ROWS] AS
    [sale_month].[dateinfo].[month].Members
    
MEMBER [measures].[Amount Change Rate] AS 
IIF(ISEMPTY([sale_month].[dateinfo].[month].currentmember.prevmember),0,[Measures].[saleAmount]/([Measures].[saleAmount],[sale_month].[dateinfo].[month].currentmember.prevmember)-1),FORMAT_STRING='0.00%'

SELECT
NON EMPTY {[Measures].[saleAmount],[measures].[Amount Change Rate]} ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [sale_month]

######单表无主键建cube
采用SQL联合主键的思想定义Attribute,在Key中定义多个column来唯一标识一行数据,NameColumn必须得定义


############formula可用的函数
formula 在schema中是用来定义<calculatemember>和<Nameset>的,对应于MDX中利用WITH MEMEBR和WITH SET来定义计算成员和命名集合
也就是所在<formula> ***<formula/>中间包含的实质上就是定义计算成员和命名集合的MDX语句,那么在MDX中对集合和元组进行操作的函数和运算规则基本上都是在formula中可用的。
包括:+,-,*,/,max,min,avg,sum,topCount,bottomCont,topPrecent,bottomPercent,crossjoin 等

猜你喜欢

转载自my.oschina.net/zhouwang93/blog/1813687
MDX