壹佰网|ERP100 - 企业信息化知识门户

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2278|回复: 8

BIEE建模技巧之 显示没有事实的维度成员

[复制链接]
发表于 2012/6/25 10:02:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。如果您注册时有任何问题请联系客服QQ: 83569622  。

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 lianle987 于 2012/6/25 10:17 编辑

众所周知,BIEE的OLAP主要可以分为两种,一种是基于Essbase等多维数据库的MOLAP,一种是基于关系数据库的ROLAP.
由于存储结构上的不同导致这两种OLAP在呈现没有事实的维度组合时有着明显的不同.
MOLAP对于没有事实的维度组合会呈现为空,具体表现为,会将维度成员的组合记录呈现出来,对应的事实指标显示为空;
ROLAP对于没有事实的维度组合则压根不会呈现,具体表现为,不会将没有事实的维度成员组合记录呈现出来.(除非你在事实表中插入了空事实)
对于ROLAP的这种方式往往不能满足业务用户的需求,对于没有事实的维度组合,业务用户要求以要将他们呈现出来,以明确的告诉他们,没有这类事实发生
那我们应该怎么办呢?
我们首先想到的可能是用左联接,即在逻辑层把维表和事实表的连接关系设置为左连接.很遗憾,这种方式对于单张维表来说是可行的,多张的话就不行了;另外,如果你设置为了左连接,那么所有的用于这个模型的地方都将是左连接,而大部分却是不需要的,这会带来严重的性能问题.(具体相关缘由请大家自行验证)

那是不是我们就没有办法了呢?我们先抛开BIEE本身来思考这个问题.让我们自己写SQL的话,我们会怎么办?
也许我们会这样做
1:首先用维表和事实表关联,并加上过滤条件查出我们需要的数据;得到结果集A
2:求需要呈现的维度的笛卡尔集,并加上过滤;得到我们关注的维度组合B
3:用B外连A得到我们要的结果!

OK,这样是比较优秀的做法,那能在IEE中实现吗?
答案当然是肯定的了!

下面我们以BIEE 11g官方的SampleApp demo为例讲解实现方法。 
注:此法同样适用于10g

上面的步骤1就不用实现了,我们直接开始步骤2吧

在物理层新建一张视图,命名为FactCrossJoin,代码如下
  1. SELECT 'Yes' Preserver FROM dual
复制代码
然后增加Preserver列,将类型设置为varchar(10);接着将其与D01 Time Day Grain和D10 Product (Dynamic Table)连接起来,如下图所示
join.jpg

注:连接条件均为1=1,这样是为了采生笛卡集的效果

接下将FactCrossJoin的Preserver字段拖到逻辑层的F0 Sales Base Measures表中,并将其聚合算法设置为max,
并将其名字改为Preserve Dimension(做到见名知意)
j.jpg
最后将Preserve Dimension字段拖到展现层,暴露给前端。

至此,模型就建完了,下面的问题是我们怎么用。

先来看看普通情况吧,2008年每周各类产品的销售如下:
132.jpg

可以明显的看到,并不是所有种类的产品在这三周都有销售的,而我们的需求是:
不管某类产品有没有销售都需要将他们呈现出来,以明显的告诉用户哪些产品没有销售,也就是如下图所示:
333.jpg

上图是怎么出来的呢?很简单,直接把我们前面在RPD中新增的Preserve Dimension字段拖进来即可!
4444.jpg

至此大功告成!
当然了,我们肯定不想Preserve Dimension这个字段出现在报表里,我们有两种办法,
一种是将其添加到过滤器里并赋予Yes的值;另一种是将该字段隐藏其来。

将该字段添加到过滤器里有个好处是,我们可以把这种功能提供给客户来选择,有的客户想看所有的数据;而有的客户则想压缩空行。

下面我们来检查一下这种做法生成的SQL吧。
  1. WITH
  2. SAWITH0 AS (select sum(T42433.Revenue) as c1,
  3. T42409.Type as c2,
  4. T42404.Per_Name_Week as c3
  5. from
  6. SAMP_PRODUCTS_D T42409 /* D10 Product (Dynamic Table) */ ,
  7. SAMP_TIME_DAY_D T42404 /* D01 Time Day Grain */ ,
  8. SAMP_REVENUE_F T42433 /* F10 Billed Rev. */
  9. where ( T42404.Calendar_Date = T42433.Bill_Day_Dt and T42404.Per_Name_Year = '2008' and T42409.Prod_Key = T42433.Prod_Key )
  10. group by T42404.Per_Name_Week, T42409.Type),
  11. SAWITH1 AS (select max(T198986.Preserver) as c1,
  12. T42409.Type as c2,
  13. T42404.Per_Name_Week as c3
  14. from
  15. SAMP_PRODUCTS_D T42409 /* D10 Product (Dynamic Table) */ ,
  16. SAMP_TIME_DAY_D T42404 /* D01 Time Day Grain */ ,
  17. (SELECT 'Yes' Preserver FROM dual) T198986
  18. where ( T42404.Per_Name_Year = '2008' )
  19. group by T42404.Per_Name_Week, T42409.Type),
  20. SAWITH2 AS (select D1.c1 as c1,
  21. D1.c2 as c2,
  22. D1.c3 as c3,
  23. D1.c4 as c4,
  24. D1.c5 as c5
  25. from
  26. (select 0 as c1,
  27. case when D1.c2 is not null then D1.c2 when D2.c2 is not null then D2.c2 end as c2,
  28. case when D1.c3 is not null then D1.c3 when D2.c3 is not null then D2.c3 end as c3,
  29. D1.c1 as c4,
  30. D2.c1 as c5,
  31. ROW_NUMBER() OVER (PARTITION BY case when D1.c2 is not null then D1.c2 when D2.c2 is not null then D2.c2 end , case when D1.c3 is not null then D1.c3 when D2.c3 is not null then D2.c3 end ORDER BY case when D1.c2 is not null then D1.c2 when D2.c2 is not null then D2.c2 end ASC, case when D1.c3 is not null then D1.c3 when D2.c3 is not null then D2.c3 end ASC) as c6
  32. from
  33. SAWITH0 D1 full outer join SAWITH1 D2 On D1.c2 = D2.c2 and D1.c3 = D2.c3
  34. ) D1
  35. where ( D1.c6 = 1 ) )
  36. select D1.c1 as c1, D1.c2 as c2, D1.c3 as c3, D1.c4 as c4, D1.c5 as c5 from ( select D1.c1 as c1,
  37. D1.c2 as c2,
  38. D1.c3 as c3,
  39. D1.c4 as c4,
  40. D1.c5 as c5
  41. from
  42. SAWITH2 D1
  43. order by c1, c3, c2 ) D1 where rownum <= 1000001
复制代码
可以看到,的确是按照我们的想法生成的。为什么会这么样呢?实际上这就是我们常说的多事实表有公共维度的情况;
首先是维度分别和事实表关联得到结果集A、B;然后在对A、B使用公共维度字段连接起来(可以看到这里使用的是全连接)

那么在这里我留下一个问题,如果这两张事实表在存在公共维度的情况下还有非公共维度应该怎么办呢?

欲知后事如何,请听下回分解。{:soso_e113:}




发表于 2012/6/25 15:55:04 | 显示全部楼层
先顶,晚上回去再细看~~CSDN同步更新不~~
发表于 2012/6/25 16:31:35 | 显示全部楼层
牛帖啊,崇拜下楼主哈
发表于 2013/3/4 15:51:06 | 显示全部楼层
学习了鸟样,不错,不错
发表于 2013/4/11 18:03:18 | 显示全部楼层
楼主你太帅气了,狂顶
发表于 2013/4/12 12:35:25 | 显示全部楼层
本帖最后由 LofyLoveXu 于 2013/4/12 12:37 编辑

无标题.png 楼主,我有这样的一个问题。想要实现的效果是,不论后面的本期和对比期是否有对应值,最左边的年龄段都全部显示,看上去跟您所讲述的是一个问题,但是我操作后的结果不正确。
我有两个维度,一个是年龄段、一个是类别,年龄段作为显示维度列,性别作为仪表盘提示,大致按照您的方法做了测试,如果不给类别值,年龄段是全部显示的,一旦给类别赋值年龄段就不能完全显示了。
求楼主给个解决方案,万分感谢!
发表于 2013/4/12 18:41:37 | 显示全部楼层
楼主您说的后一种情况怎么处理的呀,期待您的回复
发表于 2013/4/13 14:04:05 | 显示全部楼层
我又按照楼主说的方法进行了测试,可行。不过在仪表盘提示中是需要添加其他个维度表中字段的过滤,这样的话,是不是每个维度表之间都要通过这个虚表进行1=1的关联呢?
求解。
发表于 2013/9/3 08:34:42 | 显示全部楼层
BIEE建模技巧 好好学习 下{:soso_e100:}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|手机版|壹佰网 ERP100 ( 京ICP备19053597号-2 )

Copyright © 2005-2012 北京海之大网络技术有限责任公司 服务器托管由互联互通
手机:13911575376
网站技术点击发送消息给对方83569622   广告&合作 点击发送消息给对方27675401   点击发送消息给对方634043306   咨询及人才点击发送消息给对方138011526

GMT+8, 2025/11/28 22:34 , Processed in 0.029582 second(s), 19 queries , File On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表