MDX 中最大值和最小值

MDX 中最大值和最小值函数的语法和之前看到的 Sum 以及 Aggregate 等聚合函数基本上是一样的:

Max( {Set} [, Expression])

Min( {Set} [, Expression])

直接看例子,先查询出所有 Sub Category 下的 Reseller Sales Amount。

然后使用 MAX 函数查询出 Sub Category 下最大的 Reseller Sales Amount。在这里查询的范围即 SET 集合是 Sub Category 的所有成员,比较大小的依据是 Reseller Sales Amount,即在 SET 集合中查找 Reseller Sales Amount 的最大值。

比较每个 Sub Category 的 Reseller Sales Amount 和最大值的百分比。

WITH
MEMBER [Measures].[Percent of Max]
AS
([Measures].[Reseller Sales Amount]) / ([Measures].[Max Sales By Subcategory])
, FORMAT_STRING="Percent"
MEMBER [Measures].[Max Sales By Subcategory] AS
Max(
{[Product].[Subcategory].[Subcategory].Members},
([Measures].[Reseller Sales Amount])
)
SELECT
{
([Measures].[Reseller Sales Amount]),
([Measures].[Percent of Max])
} ON COLUMNS,
{[Product].[Subcategory].[Subcategory].Members} ON ROWS
FROM [Step-by-Step]

注意 Max、Min 函数与 TopCount 函数的区别:

Max、Min 函数返回的是在集合中元组对应表达式中最大或者最小的值,但 TopCount 是根据表达式查找集合中的成员。

下面查找 Reseller Sales Amount 最高的那个 Subcategory 成员。

SELECT
{
([Measures].[Reseller Sales Amount])
} ON COLUMNS,
TOPCOUNT
(
{[Product].[Subcategory].[Subcategory].Members},
1,
([Measures].[Reseller Sales Amount])
)ON ROWS
FROM [Step-by-Step]

统计集合中的元组 Count( {Set} [, Flag])

与前面的 MDX 聚合函数一样操作的对象都是集合 SET。Flag 的作用是:如果没有 Flag 或者指定 INCLUDEEMPTY,那么 Count 函数就直接返回集合中元组的数量;如果指定了 EXCLUDEEMPTY ,那么将返回与当前度量值相关联的非空的元组。

查询 Product 级别下所有成员的 Internet Sales Amount 和 Reseller Sales Amount,可以从下面的查询中看出不是所有产品都有 Internet Sales Amount 或者 Reseller Sales Amount 的销售记录。

COUNT 一下各个 Category 下 Product 成员的个数 -

WITH MEMBER [Measures].[Count of Products]
AS
COUNT(
EXISTING {([Product].[Product].[Product].Members)}
)
SELECT
[Measures].[Count of Products] ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

统计 Category 下 Reseller Sales Amount 大于等于 Internet Sales Amount 的 Products。

WITH MEMBER [Measures].[Count of Products]
AS
COUNT(
EXISTING {([Product].[Product].[Product].Members)}
)
MEMBER [Measures].[Reseller vs Internet Count of Products]
AS
COUNT(
FILTER(
EXISTING {([Product].[Product].[Product].Members)},
[Measures].[Reseller Sales Amount] >= [Measures].[Internet Sales Amount]
)
)
SELECT
{[Measures].[Count of Products],
[Measures].[Reseller vs Internet Count of Products]} ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

上面的查询结果中仍然有不准确的地方,因为在统计过程中包含了 Reseller Sales Amount 为 NULL, Internate Sales Amount 为 NULL 或者两者都为 NULL 的元组,实际上这类元组应该在统计的时候要被排除掉。

因此,加上 EXCLUDEEMPTY 关键字再来查询一下 -

但是通过观察最后的查询结果发现尽管使用了 EXCLUDEEMPTY 关键字也没有什么变化,但是确实有一些 Products 是没有 Reseller Sales Amount 数据的。其原因就在于这里会造成 Infinite Recursion 错误,只不过在这里被自动处理掉了。

有关 Infinite Recursion 的内容可以参看 MDX Step by Step 读书笔记(五) - Working with Expressions (MDX 表达式) - Infinite Recursion 和 SOLVE_ORDER 原理解析

可以通过 CrossJoin {[Measures].[Reseller Sales Amount]} 来解决这个问题,因为这样 COUNT 的时候就知道了上下文环境,元组中关联的度量值对象是 {[Measures].[Reseller Sales Amount]}。

WITH MEMBER [Measures].[Count of Products]
AS
COUNT(
EXISTING {([Product].[Product].[Product].Members)}
)
MEMBER [Measures].[Reseller vs Internet Count of Products]
AS
COUNT(
FILTER(
EXISTING {([Product].[Product].[Product].Members)},
[Measures].[Reseller Sales Amount] >= [Measures].[Internet Sales Amount]
)
)
MEMBER [Measures].[NOEMPTY Reseller vs Internet Count of Products]
AS
COUNT(
FILTER(
EXISTING {([Product].[Product].[Product].Members)},
[Measures].[Reseller Sales Amount] >= [Measures].[Internet Sales Amount]
)* {[Measures].[Reseller Sales Amount]},
EXCLUDEEMPTY
)
SELECT
{[Measures].[Count of Products],
[Measures].[Reseller vs Internet Count of Products],
[Measures].[NOEMPTY Reseller vs Internet Count of Products]} ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

DistinctCount 函数

MDX 提供了另外一种 COUNT 的形式 - DistinctCount,它可以在执行 COUNT 之前先忽略掉空的以及重复的元组然后进行统计。它其实在操作上等同于在 COUNT 函数中使用 DISTINCT 关键字:COUNT(DISTINCT ({SET}), EXCLUDEEMPTY)

它的实际语法是:DistinctCount({SET})

但是如果仅仅是需要去掉重复元组后再统计 COUNT ,并且也允许包含空的元组的统计,那么就应该使用:

COUNT(DISTINCT ({SET})) 或者 COUNT(DISTINCT ({SET}), INCLUDEEMPTY)

Generate 函数

Generate ({Set}, Expression) ,Generate 函数在这一篇笔记中已经介绍过了 -

MDX Step by Step 读书笔记(六) - Building Complex Sets (复杂集合的处理) - Generate 和 Extract 函数的使用

简单回顾一下这个函数,它类似于一个循环,相当于在集合中的每一个元组都去匹配一下表达式,符合要求的元组留下来并最终和其它一样满足要求的元组共同组成一个新的集合 SET 返回。

它还有另外的一种形式可以在聚合中用到:Generate({Set}, Expression [, Delimiter])

在这个形式中,Generate 函数仍然会迭代 SET 集合中的每一个元组并匹配表达式中的内容,符合条件的元组根据 Delimiter 分割符与其它元组形成一个字符串。

WITH
MEMBER [Measures].[Products] AS
Count(
EXISTING {[Product].[Product].[Product].Members}
)
MEMBER [Measures].[Products List] AS
Generate(
EXISTING {[Product].[Product].[Product].Members},
[Product].[Product].CurrentMember.Name,
" | "
)
SELECT
{
([Measures].[Products]),
([Measures].[Products List])
} ON COLUMNS,
{[Product].[Subcategory].Members} ON ROWS
FROM [Step-by-Step]

更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。

MDX Step by Step 读书笔记(七) - Performing Aggregation 聚合函数之 Max, Min, Count , DistinctCount 以及其它 TopCount, Generate的更多相关文章

  1. MDX Step by Step 读书笔记(七) - Performing Aggregation 聚合函数之 Sum, Aggregate, Avg

    开篇介绍 SSAS 分析服务中记录了大量的聚合值,这些聚合值在 Cube 中实际上指的就是度量值.一个给定的度量值可能聚合了来自事实表中上千上万甚至百万条数据,因此在设计阶段我们所能看到的度量实际上就 ...

  2. 《利用python进行数据分析》读书笔记--第九章 数据聚合与分组运算(一)

    http://www.cnblogs.com/batteryhp/p/5046450.html 对数据进行分组并对各组应用一个函数,是数据分析的重要环节.数据准备好之后,通常的任务就是计算分组统计或生 ...

  3. Machine Learning for hackers读书笔记(七)优化:密码破译

    #凯撒密码:将每一个字母替换为字母表中下一位字母,比如a变成b. english.letters <- c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ...

  4. 【锋利的Jquery】读书笔记七

    第七章  jquery插件 管理cookie的插件--cookie jquery插件太多没什么好讲的,百度太多 说以下 cookie插件 <!DOCTYPE html> <html& ...

  5. Android驱动开发读书笔记七

    第七章 (一)创建设备文件 1.使用cdev_init函数初始化cdec 描述设备文件需要一个cdev结构体,代码如下: struct cdev{ struct kobject kobj; struc ...

  6. 《CLR.via.C#第三版》第二部分第13章节 接口 读书笔记(七)

    这章的书写感觉很普通,是些基础的认知知识. 其中一点的重要认知,泛型接口的好处(其实也是使用泛型的好处之一):编译时类型安全&处理值类型时减少装箱. 再说点书上没有的.本来这些知识我打算另外分 ...

  7. 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构

    Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...

  8. Spring揭秘 读书笔记 七 BeanFactory的启动分析

    首先,先看我自己画的BeanFactory启动时的时序图. 第一次接触时序图,可能有些地方画的不是很符合时序图的规则,大家只关注调用顺序即可. public static void main(Stri ...

  9. how tomcat works读书笔记 七 日志记录器

    大家可以松一口气了,这个组件比较简单,这一节和前面几节想比,也简单的多. Logger接口 Tomcat中的日志记录器都必须实现org.apache.catalina.Logger接口. packag ...

随机推荐

  1. jmeter正则表达式提取器多模块相互调用

    提取return的结果 (1)例: 创建账户和转账功能 注:以下为soap协议 添加账户1 创建正则表达式提取器(提取创建的结果) 点击导入接口文档URL地址和方框内方法 同上方法添加账户2 点击正则 ...

  2. Array,ArrayList,泛型List比较

    在C#中数组Array,ArrayList,泛型List都能够存储一组对象,但是在开发中根本不知道用哪个性能最高,下面我们慢慢分析分析. 一.数组Array 数组是一个存储相同类型元素的固定大小的顺序 ...

  3. 支付宝回调JAVA版代码

    支付宝回调: 1 //这个是支付宝回调的信息 2 @RequestMapping("alipay_callback.do") 3 @ResponseBody 4 public Ob ...

  4. 数据流分段下载(Http之 Range)

    public FileStreamResult StreamUploadedSongs(int id) { byte[] song = db.UploadedSongs.Where(x => x ...

  5. Ubuntu 16.04 LTS 搭建ftp服务器

    其实我之前搭建好了,但是最近我上来看好像跟没搭建一样呢,于是我从新搭建一遍? 我的ubuntu版本: cat /etc/issue Ubuntu 16.04 LTS \n \l 1.安装vsftpd( ...

  6. MT4编程初级手册

    http://www.fxunion.com/college/2015/17554.html

  7. P1197 [JSOI2008]星球大战 并查集 反向

    题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...

  8. Java 处理 iphone拍照后 图片EXIF属性翻转90度的方法

    http://blog.csdn.net/z69183787/article/details/50320821 Java获取照片EXIF信息 http://blog.csdn.net/ghsau/ar ...

  9. React Native之基于AsyncStorage的离线缓存框架设计

    1.为什么要离线缓存? 宏观上来说: 提升用户体验: 我们要为用户提供流畅的APP操作体验,但我们无法保证所有用户的网络流畅度是好的,所以我们需要离线缓存来提升用户体验. 节省流量: 节省流量又分为两 ...

  10. java 客户端调用 go grpc服务端问题总结

    1.网络不通,无法调试. 2.proto文件更改后要及时通知客户端. 3.grpc跨语言调用多语言使用很方便.