您的位置:首页 > 数据库 > Oracle

Oracle分析函数model使用时需要注意的几个地方(二)

2018-03-23 13:28 1451 查看
接着上文

Oracle分析函数model使用时需要注意的几个地方(一)

分析函数中的model函数功能强大,对于做数据分析的人来说绝对是一个利器。

我曾经用model函数改写了数十个用存储过程实现的报表取数,一个SQL语句就完全替代了一个上百行代码的存储过程,而且报表口径也完成了统一,这一点在我另外一篇文章中做了详细说明:

基于model函数建设口径统一的统计指标库

虽然model函数很强大,但刚接触的时候还是不免有很多需要留意的地方,一不小心就会发现统计结果与预想的不一样。这里罗列几个方面并给出解决方案:

3、错误ORA-25137 Data value out of range

model语句中组装的新的分类,长度不能超过原表dimension字段的长度。否则就会报ORA-25137这个错。

SQL> desc t_saleamount
Name     Type         Nullable Default Comments
-------- ------------ -------- ------- --------
YEARMON  DATE         Y
PRODTYPE VARCHAR2(10) Y
QUANTITY NUMBER(10)   Y
AMOUNT   NUMBER(12,2) Y

SQL> select * from t_saleamount where yearmon=date'2018-03-01' and prodtype in('啤酒','王老吉','饮料')
2  model
3  partition by(yearmon)
4  dimension by (prodtype)
5  measures(amount,quantity)
6  (quantity['啤酒、王老吉、饮料']=sum(quantity)[prodtype in('啤酒','王老吉','饮料')]
7  ,amount['啤酒、王老吉、饮料']=sum(amount)[prodtype in('啤酒','王老吉','饮料')]);

ORA-25137: Data value out of range


上述语句报错的原因是字符串【‘啤酒、王老吉、饮料’】超过了PRODTYPE字段VARCHAR2(10)的长度。

解决办法1.修改表结构,加大dimension字段的长度

SQL> alter table t_saleamount modify PRODTYPE VARCHAR2(20);
Table altered
SQL> select * from t_saleamount where yearmon=date'2018-03-01' and prodtype in('啤酒','王老吉','饮料')
2  model
3  partition by(yearmon)
4  dimension by (prodtype)
5  measures(amount,quantity)
6  (quantity['啤酒、王老吉、饮料']=sum(quantity)[prodtype in('啤酒','王老吉','饮料')]
7  ,amount['啤酒、王老吉、饮料']=sum(amount)[prodtype in('啤酒','王老吉','饮料')])
8  /
YEARMON     PRODTYPE                 AMOUNT   QUANTITY
----------- -------------------- ---------- ----------
2018/3/1    饮料                      43348         32
2018/3/1    啤酒                      11464       3785
2018/3/1    王老吉                    20524       5870
2018/3/1    啤酒、王老吉、饮料         75336       9687


实际场景中,大部分时候表结构是无法修改的,也可能是对一个查询结果进行model,更加无从修改。此时可以使用第二种办法:

解决办法2.增加虚拟字段

SQL> alter table t_saleamount modify PRODTYPE VARCHAR2(10);
Table altered

SQL>
SQL> select decode(prodtype,'0',newprodtype,prodtype) prodtype,yearmon,amount,quantity from (
2  select prodtype,lpad('0',50,'0') as newprodtype,yearmon,amount,quantity
3    from t_saleamount
4    where yearmon=date'2018-03-01' and prodtype in('啤酒','王老吉','饮料')
5  )
6  model
7  partition by(yearmon)
8  dimension by (newprodtype,prodtype)
9  measures(amount,quantity)
10  (quantity['啤酒、王老吉、饮料','0']=sum(quantity)[any,prodtype in('啤酒','王老吉','饮料')]
11  ,amount['啤酒、王老吉、饮料','0']=sum(amount)[any,prodtype in('啤酒','王老吉','饮料')]);
PRODTYPE                                           YEARMON         AMOUNT   QUANTITY
-------------------------------------------------- ----------- ---------- ----------
饮料                                               2018/3/1         43348         32
啤酒                                               2018/3/1         11464       3785
王老吉                                             2018/3/1         20524       5870
啤酒、王老吉、饮料                                 2018/3/1         75336       9687


这里用rpad函数虚拟了一个50个0字符的newprodtype字段,根据需要可以自定义长度。

此时dimension的维度变成了2维,因此在model中需要对2个维度都进行设置。这里解释一下这个model语句:

quantity[‘啤酒、王老吉、饮料’,’0’]=sum(quantity)[any,prodtype

in(‘啤酒’,’王老吉’,’饮料’)]

=号左边的[]内,分别表示model结果集里newprodtype=’啤酒、王老吉、饮料’和prodtype=’0’。

=号右边的[]内,表示对原表的筛选条件,any表示newprodtype取所有记录,也可以用1=1之类恒等式替代;prodtype in(‘啤酒’,’王老吉’,’饮料’)是对prodtype字段值的筛选。

此时的查询结果实际上是这样的:



经过decode转换后,得到了我们需要的结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: