暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

理解model高级语句

原创 听见风的声音 2023-03-01
1033


     Oracle 从10g开始支持model高级语句,使用model语句,可以在表上定义一个数据立方体,这个立方体由它的维度和度量定义,并通过规则对每个单元的值进行计算,这相当于是把关系表转换成了多维数组,这个多维不止可以是三维,可以是包含一维、二维的任意维度。这样也就提供了一种在oltp数据库里进行olap的方法。

1 model语句的基本语法

       model语句的语法在Oracle数据库里是比较复杂的,其基本语法可以从一个简单的例子看到,示例代码中用到的基表已经实现创建,只有三条数据

SQL> select * from t;
      DIM1       DIM2      VALUE
---------- ---------- ----------
         0          0          1
         0          1          2
         1          0          3
复制

一个简单的model语句如下面所示:

select * from t 
model
dimension by (dim1, dim2)--定义维度
measures (value, 0 result)---定义度量
(                                 -----定义规则
  result[0,0] = -1
)
复制

     model后面由三部分组成,dimension定义数据立方体的维度,定义维度的列必须是基表里的列,measures定义数据立方体的度量,度量可以来自基表,也可以自己定义,最后括弧里面定义的是用于计算度量的规则集。这些规则集默认按照顺序应用的刚才定义的数据立方体上。规则集必须存在,但可以为空,下面看一下数据立方体是怎么定义的。

2 定义立方体

     model语句的执行类似于过程语言,先定义一个数据立方体,然后按照顺序在这个立方体上应用规则里定义的规则。通过一个规则集为空的例子可以简单直接地看到model语句是如何定义数据立方体的。

SQL> with t(id, value) as (
          select rownum, rownum from dual connect by level <= 3
        )
        select * from t
        model
        dimension by (id)
        measures (value,100 r1,100 r2)
        (
        ) ;
          ID      VALUE         R1         R2
  ---------- ---------- ---------- ----------
           1          1        100        100
           2          2        100        100
           3          3        100        100
复制

    上面的示例中,规则集为空,定义立方体后没有应用任何规则,基表由with语句定义,是一个3行3列的表,由model定义的立方体中,使用基表中的id作为维度,value作为度量,另外又定义了两个度量r1,r2,基表中有的度量值使用基表中的值作为数据立方体相应单元的值,基表中没有的值则使用度量中指定的值(度量定义前面的数字)作为默认值。

3 规则的定义和使用

     model语句的复杂性在于它支持复杂的规则定义,为了简单直观,这里还是使用示例来说明

select * from t 
model
dimension by (dim1, dim2)
measures (value, cast(null as number) result)
(
  result[0,0] = -1,       --位置引用
  result[dim1=1, dim2=0] = -3, ---符号引用
  result[-1, for dim2 in (select count(*) from dual)] = -4, --位置引用
  result[-2, dim2=1] = -10,   --混合引用
  result[-3, dim2= -1] = -100,    --混合引用
  result[-4, -1] = -1000 ----位置应用
)
order by dim1, dim2;
复制

     表t还是上面定义的表,这里定义了6条规则,要想理解这6条规则,首先要理解几个概念和定义。首先,对每一条规则来说,等号的左边是要操作的单元,等号的右边是对单元的赋值或者操作,等号左边需要引用要操作的单元,这里有三种引用方法,符号维度引用、位置维度引用和混合维度引用,所谓的符号维度引用,必须是一个包含维度名称的表达式,比如上面示例中的result[dim1=1, dim2=0],除了符号位置应用之外的则是位置维度引用,简单的位置维度引用比如上面例子中的result[0,0],值得注意的是,像result[-1, for dim2 in (select count(*) from dual)]这样复杂的引用也是位置维度引用,混合维度引用是在多个维度引用时,一部分维度是符号维度引用,一部分维度是位置维度引用,如上面的示例中的result[-2, dim2=1]。

      为什么要区分符号维度引用和位置维度应用,这两种引用的区别在哪里?简单来说,符号维度引用用来引用已经存在的数据,位置维度引用可以用来引用必须要加入的数据,这些数据本来不存在。至于混合维度引用,上面的规则依然使用,混合维度里符号维度必须为已存在的数据,位置维度则可以为不存在的需要加入的数据。

      这样的区分有实际意义吗?其实是有的,关键在于Oracle对立方体里的单元的处理方式。Oracle对立方体内的单元的处理方式有三种,有三个关键字update/upsert all/upsert来定义,update只更新立方体内已有的数据,upsert在更新存在的单元的同时,也创建位置维度引用的不存在的单元,upsert all和upsert不同的是,它还创建混合应用中符号维度引用已经存在的单元。默认的处理方式是upsert。说起来比较枯燥,还是使用示例来说明比较直观。先看默认的方式即upsert

select * from t 
model
dimension by (dim1, dim2)
measures (value, cast(null as number) result)
(
  result[0,0] = -1,       --位置引用
  result[dim1=1, dim2=0] = -3, ---符号引用
  result[-1, for dim2 in (select count(*) from dual)] = -4, --位置引用
  result[-2, dim2=1] = -10,   --混合引用
  result[-3, dim2= -1] = -100,    --混合引用
  result[-4, -1] = -1000 ----位置应用
)
order by dim1, dim2;

DIM1       DIM2      VALUE     RESULT
---------- ---------- ---------- ----------
  -4         -1                 -1000    ---位置引用
  -1          1                    -4     ----位置引用。dim2 维度是select语句定义的
   0          0          1         -1     ---数值数据集
   0          1          2
   1          0          3         -3
复制


      上面的示例中,注释已经说的比较清除了,后面三行数据引用的是原始的数据立方体里的数据,另外两行数据的单元都是位置维度引用的。混合维度引用和符号维度引用的单元在这里没有出现。下面看一下update的情况

select * from t 
           model
           dimension by (dim1, dim2)
           measures (value, cast(null as number) result)
           rules update 
           (
             result[0,0] = -1,       --位置引用
             result[dim1=1, dim2=0] = -3, ---符号引用
             result[-1, for dim2 in (select count(*) from dual)] = -4, --位置引用
             result[-2, dim2=1] = -10,   --混合引用
             result[-3, dim2= -1] = -100,    --混合引用
             result[-4, -1] = -1000 ----位置应用
           )
           order by dim1, dim2;


           DIM1       DIM2      VALUE     RESULT
     ---------- ---------- ---------- ----------
              0          0          1         -1
              0          1          2
              1          0          3         -3
复制


只有原始数据立方体内存在的数据。最后是upsert all

select * from t 
   model
   dimension by (dim1, dim2)
   measures (value, cast(null as number) result)
   rules upsert all 
   (
     result[0,0] = -1,       --位置引用
     result[dim1=1, dim2=0] = -3, ---符号引用
     result[-1, for dim2 in (select count(*) from dual)] = -4, --位置引用
     result[-2, dim2=1] = -10,   --混合引用
     result[-3, dim2= -1] = -100,    --混合引用
     result[-4, -1] = -1000 ----位置应用
   )
   order by dim1, dim2;

           DIM1       DIM2      VALUE     RESULT
        ---------- ---------- ---------- ----------
              -4         -1                 -1000  --位置引用
              -2          1                   -10   --混合引用,符号引用的维度在初始数据集中存在
              -1          1                    -4   --位置引用
               0          0          1         -1  --初始数据集
               0          1          2
               1          0          3         -3

        6 rows selected.
复制


      上面出现的数据包含数据立方体原始数据,位置维度引用数据,以及一行混合维度引用数据,这行混合维度应用数据在这里出现的原因是它的符号维度应用dim2=1在原始的数据立方体内存在,尽管它的位置维度引用-2在原始数据立方体里不存在,而另一个混合维度引用单元result[-3, dim2= -1]在结果集里不存在是因为它的符号维度引用dim2= -1在原始数据立方体里不存在。从上面的例子里可以看出,使用符号维度引用原始立方体里不存在的维度值是没有意义的,做的计算也只是无用功。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论