代码改变世界

MDX中TopN函数的使用

2009-02-04 01:06  Yin.P  阅读(2136)  评论(0编辑  收藏  举报

  MDX中的TopN函数是指一类函数,这类函数的作用是从一个集合中选择出满足某个阈值或百分比的元组集合。本文主要介绍TopSum, BottomSum, TopPercent和BottomSum函数。

  在实际应用中我们可能会遇到一些需求,需要我们回答类似于"最少销售哪些产品或销售多少产品才能使销量(销售额)达到某个值"、"销售量在前xx%的产品所属的产品分类有哪些"、"客户贡献在前xx%的客户中,对每一个客户,其购买的前xx%的产品所属的产品分类有哪些"等这样的问题。这些问题在MDX中都可以通过TopN系列函数来解决。

TopSum和BottomSum

    TopSum函数有三个参数,第一个参数是输入集合;第二个参数是阈值或临界值;第三个参数是数值表达式。这个函数会把集合中的元组按数值表达式降序排列,再从中选出数值表达式的结果之和不大于临界值(第二个参数)的元组集合。如下面的代码:

TopSum
SELECT 

    
[Measures].[Unit Sales] 
ON COLUMNS, 

    TopSum( 
        Descendants( 
            
[Product].[Product Category - Product Class].CurrentMember,
            
[Product].[Product Category - Product Class].[Product]
            SELF 
        ), 
        
300
        
[Measures].[Unit Sales] 
    ) 
ON ROWS 
FROM [Warehouse and Sales]

 

  上面的MDX查询就得到了要达到300的销售量,最少要销售哪些产品。这个查询在执行的时候会将Descendants函数得到的集合按[Measures].[Unit Sales]降序排列,然后从中选出[Measures].[Unit Sales]度量值的汇总不大于300的最少产品的集合。这个是TopSum的功能,而BottomSum的功能与其类似,不过BottomSum的排序方向正好相反,它是按升序排列,再从中找出达到这个临界值的最大集合。而BottomSum回答的问题也类似于TopSum,即达到某个值,最多要销售哪些产品或多少产品。 

 

TopPercentBottomPercent

    TopPercentBottomPercent也有三个参数,第一个是输入集合;第二个是一个表示百分数的数值,范围从0-100;第三个参数是数据值表达式。TopPercent函数会把集合按数值表达式按升序排序,然后从中找出一个集合,使这个集合的数值表达式汇总不大于设定的相对于总量的百分之数。如下面的代码:

TopPercent
SELECT 
{     
    
[Measures].[Unit Sales]     
ON 0

    TopPercent( 
        Descendants( 
            
[Product].[Product Category]
            
[Product].[Product Category].[Product Category]
            SELF 
        ), 
        
30
    
[Measures].[Unit Sales] 
    ) 
ON 1 
FROM [Warehouse and Sales] 

 

  上面的MDX查询可以得到销售量排在前30%的产品分类有哪些。TopSum类似,这个查询会将Descendants得到的集合按[Measures].[Unit Sales]降序排列,然后从中选出前30%的产品类型数据。BottomPercent的功能与TopPercent类似,同样只是排序方向不同而已。另外,可能还有一种查询需求,要求找出销售量在前20%的产品分类的前提下,进一步了解每个客户购买的前10%的产品分类是什么。如下面的查询就回答了这个问题。它得到的结果表示对于交易额排在前20%的客户,其购买的前10%的产品分类有哪些。  

TopPercent II
SELECT 

    
[Measures].[Store Sales] 
ON COLUMNS, 

    Generate( 
        TopPercent( 
            Descendants(
[Customer].[Customer],[Customer].[Customer].[Customer],SELF), 
            
20
            
[Measures].[Store Sales] 
        ), 
        CrossJoin( 
            {
[Customer].[Name].CurrentMember}, 
            {
[Product].[Product Category]
                TopPercent(                     
                    Descendants(
[Product].[Product Category][Product].[Product Category].[Product Category],SELF), 
                    
10
                    
[Measures].[Store Sales] 
                ) 
            } 
        ) 
    ) 
ON ROWS 
FROM [Warehouse and Sales]