例四:另一种叉积的用法
SELECT { CROSSJOIN( [Product].[Product Category - Product Class].[产品目录], [Store].[Store Name].[Store Name] ) } ON COLUMNS, { [Store].[Sales Country - Sales Region - Sales District Id - Region].[地区] } ON ROWS FROM [Foodmart多维数据立方] WHERE [Time By Day].[month_of_year].&[3]
例五:第三种叉积用法
SELECT { [Product].[Product Category - Product Class].[产品目录] }* { [Store].[Store Name].[Store Name] } ON COLUMNS, { [Store].[Sales Country - Sales Region - Sales District Id - Region].[地区] } ON ROWS FROM [Foodmart多维数据立方] WHERE [Time By Day].[month_of_year].&[3]
例四和例五都是叉积的使用方法,可以得到和例三相同的结果。因为在SSAS中不能直接查看两个轴以上的查询,但是可以使用叉积的方式将三个轴以上的查询“平面化”到两个轴中。这样在理论上就可以直接在SSAS中查看多个轴的数据。这里我之所以要讲“理论上”,是因为叉积这种运算复杂度相当地高,如果将多个维度的元组集合进行叉积的话可能等待很久也得不到结果,计算机甚至会因为大量的运算而中断程序。所以在实际中要尽量控制这样的用法。如果要用最好首先将数据控制在一个非常有限的范围之内,减少叉积带来的运算开消。
b) FROM 子句
FROM子句表示MDX查询的来源多维数据集,FROM子句中只能包含一个多维数据集,也就是说同一个MDX查询只能来自于同一个多维数据集,而不能像SQL查询一样将多个数据表连接起来。另外,MDX中的FROM子句也可以是另一个MDX查询得到的一个子多维数据集,这样就可以更加复杂的MDX查询。如下面的例六所示:
例六:包含子多维数据集的复杂查询
SELECT { [Product].[Product Category - Product Class].[产品目录] }* { [Store].[Store Name].[Store Name] } ON COLUMNS, { [Store].[Sales Country - Sales Region - Sales District Id - Region].[地区] } ON ROWS FROM ( SELECT ( { [Time By Day].[quarter].&[Q1] } ) ON COLUMNS FROM [Foodmart多维数据立方] )
c) WHERE 子句
WHERE子句的另一个名称是切片器轴,顾名思义它的作用主要就是对多维数据集进行切片和切块操作,限制数据集的大小。看下面的两个例子:
例七:多维数据集切片操作
SELECT { [Product].[Product Category - Product Class].[产品目录] }* { [Store].[Store Name].[Store Name] } ON COLUMNS, { [Store].[Sales Country - Sales Region - Sales District Id - Region].[地区] } ON ROWS FROM [Foodmart多维数据立方] WHERE ([Store].[Store Manager].&[Byrd])
图十:切片得到的结果
例七在前面叉积例子的基础上进行了切片操作,将数据限制在了Store Manager为Byrd的范围内。例七的查询得到的结果数据集从逻辑上包含三个轴,即产品目录、门店名称、地区编号。经过切片后,保留了产品目录和门店名称两个轴,另一个地区因为切片操作只剩下Byrd所对应的地区。查询结果如图十所示。
例八:多维数据集切块操作
SELECT NON EMPTY { [Product].[Product Category - Product Class].[产品目录] }* { [Store].[Store Name].[Store Name] } ON COLUMNS, NON EMPTY { [Store].[Sales Country - Sales Region - Sales District Id - Region].[地区] } ON ROWS FROM [Foodmart多维数据立方] WHERE ( [Time By Day].[quarter].&[Q1]:[Time By Day].[quarter].[Q2], [Store].[Store].&[18]:[Store].[Store].&[20], [Product].[Product Category].&[Canned Clams]:[Product].[Product Category].&[Canned Sardines] )
图十一:切块所得到的结果
例八在前面叉积的基础上进行了切块操作,分别在时间维度、门店维度、产品维度上进行了限制。图十一是这个MDX查询所得到的结果。
d) WITH 子句
WITH子句用于创建临时的命名计算成员及命名集合。通过WITH子句创建的命名计算成员和命名集合其生命周期有限,只限于与WITH子句相邻的MDX查询,当MDX查询结束后,用WITH子句创建的命名计算或命名集合也随之失效。如果要创建在整个会话过程中都保持有效的命名计算和命名集合的话,就要使用CREATE MEMBER和CREATE SET语句。
下面的例子演示了临时命名计算和临时命名集合的用法和查询结果:
例九:临时命名计算和临时命名集合的使用
WITH MEMBER [Measures].[Avg Of Units Shipped] AS ’AVG ( { [Product].[Product].[Product] }, [Measures].[Units Shipped] )’ ,FORMAT_STRING=’###,###,###,##0.00’ SET [CROSSSET_StoreName] AS ’{ [Store].[Store Name].[Store Name].[Store 1] }’ SET [CROSSSET_TIME] AS ’{ [Time By Day].[month_of_year].[month_of_year] }’ SELECT NON EMPTY { [Measures].[Avg Of Units Shipped] } ON COLUMNS, NON EMPTY [CROSSSET_StoreName]*[CROSSSET_TIME] ON ROWS FROM [Foodmart多维数据立方]
图十二:临时命名计算和命名集合的查询结果
WITH MEMBER语句最后的FORMAT_STRING是用于格式化数据结果的,在例九中,我把得到的平均值结果格式化为了保留两位小数,并进行千分位分隔。其它的常用格式符还有PERCENT、CURRENCY等。