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. 【转】crontab实用手册

    前言 crontab是Unix和Linux用于设置周期性被执行的指令,是互联网很常用的技术,很多任务都会设置在crontab循环执行,如果不使用crontab,那么任务就是常驻程序,这对你的程序要求比 ...

  2. python算法双指针问题:二分查找

    这里要注意的是//向下取整,下次循环时,如果大于查找的数字,start+1. 并且,只能向下取整,如果向上取整. 那么,在比较第一个数时,start = 0 .end = 1.mid = 1.就会进入 ...

  3. springbank 开发日志 Spring启动过程中对自定义标签的处理

    这篇随笔的许多知识来源于:http://www.importnew.com/19391.html 之所以会去看这些东东,主要是希望能够模仿spring mvc的处理流程,做出一套合理的交易处理流程. ...

  4. 解决/bin/sh: 1: syntax error: "(" unexpected错误,以及更换bash仍然无法解决的问题

    编译文件的时候出现 /bin/sh: 1: syntax error: "(" unexpected 错误. 网上查到的资料都是: (1)在脚本前写#!/bin/bash (2)执 ...

  5. Codeforces 524E Rooks and Rectangles 线段树

    区域安全的check方法就是, 每行都有哨兵或者每列都有哨兵,然后我们用y建线段树, 维护在每个y上的哨兵的x的最值就好啦. #include<bits/stdc++.h> #define ...

  6. 菜单联动,select联动菜单(搜索之后默认选中)

    框架:thinkphp php控制器代码: $schedulelist = M('schedule')->getField('sid,schedule_name'); $this->ass ...

  7. 分布式系统缓存系列之guava cache

      guava是google的一个开源java框架,其github地址是 https://github.com/google/guava.guava工程包含了若干被Google的 Java项目广泛依赖 ...

  8. Enrolment API

    由于Moodle 2.0有一个用户注册的新概念,它们完全独立于角色和功能.能力通常与注册状态结合使用. 什么是注册? 登记的用户可以完全参加一门课程.活跃用户注册允许用户输入课程.只有注册的用户可能是 ...

  9. AngularJS获取项目中定义的json文件

    项目结构: 文件夹js位于根路径下 $http.get('js/app/contact/contacts.json').then(function (res) { /*下面就是获取到的数据*/ $sc ...

  10. 002.Docker安装部署

    一 docker安装-CentOS系统 1.1 docker自动安装脚本 root@docker:~# wget -qO- https://get.docker.com/ | sh 或—— root@ ...