Oracle SQL高級編程——Model子句全解析

參見 《Oracle SQL高級編程》。

第一個例子,初步認識

SH@ prod> col product format a30
SH@ prod> col country format a10
SH@ prod> col region format a10
SH@ prod> col year format 9999
SH@ prod> col week format 99
SH@ prod> col sale format 999999
SH@ prod> set linesize 180 pagesize 100
SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules automatic order(
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)] )
 11  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998    1       8.88      58      67.03
Xtend Memory                   Australia   1998    2     14.758      29     35.268
Xtend Memory                   Australia   1998    3     20.656      29     35.388
Xtend Memory                   Australia   1998    4       8.86      29     17.694
Xtend Memory                   Australia   1998    5      14.82      30      35.76
Xtend Memory                   Australia   1998    6      8.942      59     52.902
Xtend Memory                   Australia   1998    9      2.939      59     61.719
Xtend Memory                   Australia   1998   10        .01     118    114.831
Xtend Memory                   Australia   1998   12      -14.9      60       44.7
Xtend Memory                   Australia   1998   14     11.756      59     70.536
Xtend Memory                   Australia   1998   15      5.878      59     52.902
Xtend Memory                   Australia   1998   17     11.756      59     70.536
Xtend Memory                   Australia   1998   18      8.817     118    114.621
Xtend Memory                   Australia   1998   19      2.919      59     53.082
Xtend Memory                   Australia   1998   21       2.98      60      62.58
Xtend Memory                   Australia   1998   23    -11.756     118    105.804
Xtend Memory                   Australia   1998   26     11.756     118    129.316
Xtend Memory                   Australia   1998   27     14.632      58     60.396
Xtend Memory                   Australia   1998   28       .202      58      43.29
Xtend Memory                   Australia   1998   29    -14.228      58      43.29
Xtend Memory                   Australia   1998   34     -2.886     115    112.554
Xtend Memory                   Australia   1998   35     -8.638      58     51.768
Xtend Memory                   Australia   1998   38    -11.464     116    104.376
Xtend Memory                   Australia   1998   39     -5.792     116    121.512
Xtend Memory                   Australia   1998   40    -11.544      58     51.768
Xtend Memory                   Australia   1998   41    -17.376      58     52.488
Xtend Memory                   Australia   1998   42     -5.832     116    127.384

Model子句剖析

在一個使用MODEL子句的SQL語句中,有3組列:分區列,維度列以及度量值列。
上一個例子中:
partition by (product , country)指定了分區列,
dimension by (year , week)指定了維度列,也就是指向數元素的索引,
measures (0 inventory , sale , receipts)指定了度量值列。

rules automatic order(
        inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
                                    - sale[cv(year) , cv(week)] + 
                                    + receipts[cv(year) , cv(week)] )

這個子句表示規則。
這個是一個遞推的規則:本週的庫存量 = 上週的 – 賣掉的 + 新進的。
Cv函數表示規則表達示左側中的索引的值。

用位置標記進行UPSERT操作

有則修改,沒有則插入。

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules automatic order(
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)] ,
 11  sale[1997 , 1] = 0 ,
 12  receipts[1997 , 1] = 0 )
 13  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1997    1          0       0          0
Xtend Memory                   Australia   1998    1       8.88      58      67.03
Xtend Memory                   Australia   1998    2     14.758      29     35.268
Xtend Memory                   Australia   1998    3     20.656      29     35.388
Xtend Memory                   Australia   1998    4       8.86      29     17.694
Xtend Memory                   Australia   1998    5      14.82      30      35.76
Xtend Memory                   Australia   1998    6      8.942      59     52.902
Xtend Memory                   Australia   1998    9      2.939      59     61.719
Xtend Memory                   Australia   1998   10        .01     118    114.831
Xtend Memory                   Australia   1998   12      -14.9      60       44.7

修改了1998年的初始值,下面其它月份的值也受到了影響,因爲是遞推的。

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules automatic order(
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)] ,
 11  sale[1998 , 1] = 0 ,
 12  receipts[1998 , 1] = 0 )
 13  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998    1          0       0          0
Xtend Memory                   Australia   1998    2      5.878      29     35.268
Xtend Memory                   Australia   1998    3     11.776      29     35.388
Xtend Memory                   Australia   1998    4       -.02      29     17.694
Xtend Memory                   Australia   1998    5       5.94      30      35.76
Xtend Memory                   Australia   1998    6       .062      59     52.902
Xtend Memory                   Australia   1998    9      2.939      59     61.719
Xtend Memory                   Australia   1998   10        .01     118    114.831
Xtend Memory                   Australia   1998   12      -14.9      60       44.7
Xtend Memory                   Australia   1998   14     11.756      59     70.536

用符號標記進行UPDATE操作(不能INSERT)

SH@ prod> select product , country , year , week , sale  from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model return updated rows 
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures ( sale )
  7  rules(  sale[year in(2000 , 2001) , week in (1 , 52 , 53 )] order by year , week 
  8  = sale[cv(year) , cv(week)] * 1.10 )
  9  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK    SALE
------------------------------ ---------- ----- ---- -------
Xtend Memory                   Australia   2000    1      51
Xtend Memory                   Australia   2000   52      74
Xtend Memory                   Australia   2001    1     101
Xtend Memory                   Australia   2001   52      25

因爲是return updated rows所以只返回了四行,不存在的行並不會被插入。

針對維度用FOR進行UPSERT操作

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules automatic order(
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)] ,
 11  sale[2002, for week from 1 to 53 increment 1 ] = 0 ,
 12  receipts[2002 , for week from 1 to 53 increment 1] = 0 )
 13  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998    1       8.88      58      67.03
Xtend Memory                   Australia   1998    2     14.758      29     35.268
Xtend Memory                   Australia   1998    3     20.656      29     35.388
Xtend Memory                   Australia   1998    4       8.86      29     17.694
Xtend Memory                   Australia   1998    5      14.82      30      35.76

不加RETURN UPDATED ROWS

下面的語句與上數第二個是一樣的,只是沒有加RETURN UPDATED ROWS。會返回所有行。

SH@ prod> select product , country , year , week , sale  from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model 
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures ( sale )
  7  rules(  sale[year in(2000 , 2001) , week in (1 , 52 , 53 )] order by year , week 
  8  = sale[cv(year) , cv(week)] * 1.10 )
  9  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK    SALE
------------------------------ ---------- ----- ---- -------
Xtend Memory                   Australia   1998    1      58
Xtend Memory                   Australia   1998    2      29
Xtend Memory                   Australia   1998    3      29
Xtend Memory                   Australia   1998    4      29
Xtend Memory                   Australia   1998    5      30
Xtend Memory                   Australia   1998    6      59
Xtend Memory                   Australia   1998    9      59
Xtend Memory                   Australia   1998   10     118
Xtend Memory                   Australia   1998   12      60

位置標記的UPSERT與RETURN UPDATED ROWS

由於規則只更新了一行,所以一定只返回一行。

SH@ prod> select product , country , year , week , sale  from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' 
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures ( sale )
  7  rules(  sale[2000,1] = 0 )
  8  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK    SALE
------------------------------ ---------- ----- ---- -------
Xtend Memory                   Australia   2000    1       0

Model子句中規則的求解順序

下面的語句會報錯,因既沒有顯式的指定求解順序,又沒有加Automatic Order,此時Oracle會使用Sequential Order這種順序,並不適合這個規則。

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' and week < 10
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules (
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)])
 11  order by product , country , year , week ;
select product , country , year , week , inventory , sale , receipts from sales_fact
                                                                          *
ERROR at line 1:
ORA-32637: Self cyclic rule in sequential order MODEL

添加了Sequential Order之後,與上面的錯誤是一樣的

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' and week < 10
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules sequential order (
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)])
 11  order by product , country , year , week ;
select product , country , year , week , inventory , sale , receipts from sales_fact
                                                                          *
ERROR at line 1:
ORA-32637: Self cyclic rule in sequential order MODEL

解決辦法1,添另Automatic Order:

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' and week < 10
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules automatic order (
  8  inventory[year , week] = nvl(inventory[cv(year) , cv(week)-1] , 0 )
  9  - sale[cv(year) , cv(week)] 
 10  + receipts[cv(year) , cv(week)])
 11  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998    1       8.88      58      67.03
Xtend Memory                   Australia   1998    2     14.758      29     35.268
Xtend Memory                   Australia   1998    3     20.656      29     35.388
Xtend Memory                   Australia   1998    4       8.86      29     17.694
Xtend Memory                   Australia   1998    5      14.82      30      35.76
Xtend Memory                   Australia   1998    6      8.942      59     52.902
Xtend Memory                   Australia   1998    9      2.939      59     61.719
Xtend Memory                   Australia   1999    1      2.676      54     56.196
Xtend Memory                   Australia   1999    3       4.73      95      99.33
Xtend Memory                   Australia   1999    4       4.73      41       40.5
Xtend Memory                   Australia   1999    5     10.064      80     85.344
Xtend Memory                   Australia   1999    6      6.014      41      36.45
Xtend Memory                   Australia   1999    8     -2.196     103    100.914
Xtend Memory                   Australia   1999    9     13.806      53     69.342
Xtend Memory                   Australia   2000    1    -11.675      47     35.025
Xtend Memory                   Australia   2000    3     11.602      93    105.012
Xtend Memory                   Australia   2000    4      6.948      47     41.886
Xtend Memory                   Australia   2000    5     16.288      47      56.04
Xtend Memory                   Australia   2000    7          0      71       70.8
Xtend Memory                   Australia   2000    8      2.327      47     48.867
Xtend Memory                   Australia   2001    1      4.634      92     96.894
Xtend Memory                   Australia   2001    2     21.182     118    134.928
Xtend Memory                   Australia   2001    3     35.354      47     61.412
Xtend Memory                   Australia   2001    4     24.294     257     245.64
Xtend Memory                   Australia   2001    5      26.76      93     95.906
Xtend Memory                   Australia   2001    6     24.516      22     20.196
Xtend Memory                   Australia   2001    7      17.52      70     62.964
Xtend Memory                   Australia   2001    8     19.646      46     48.186
Xtend Memory                   Australia   2001    9     21.984      93     95.008

解決辦法2,具體指定順序:

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' and week < 10
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules (
  8  inventory[year , week] order by year , week 
  9  = nvl(inventory[cv(year) , cv(week)-1] , 0 )
 10  - sale[cv(year) , cv(week)] 
 11  + receipts[cv(year) , cv(week)])
 12  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998    1       8.88      58      67.03
Xtend Memory                   Australia   1998    2     14.758      29     35.268
Xtend Memory                   Australia   1998    3     20.656      29     35.388
Xtend Memory                   Australia   1998    4       8.86      29     17.694
Xtend Memory                   Australia   1998    5      14.82      30      35.76
Xtend Memory                   Australia   1998    6      8.942      59     52.902
Xtend Memory                   Australia   1998    9      2.939      59     61.719
Xtend Memory                   Australia   1999    1      2.676      54     56.196
Xtend Memory                   Australia   1999    3       4.73      95      99.33
Xtend Memory                   Australia   1999    4       4.73      41       40.5
Xtend Memory                   Australia   1999    5     10.064      80     85.344
Xtend Memory                   Australia   1999    6      6.014      41      36.45
Xtend Memory                   Australia   1999    8     -2.196     103    100.914
Xtend Memory                   Australia   1999    9     13.806      53     69.342
Xtend Memory                   Australia   2000    1    -11.675      47     35.025
Xtend Memory                   Australia   2000    3     11.602      93    105.012
Xtend Memory                   Australia   2000    4      6.948      47     41.886
Xtend Memory                   Australia   2000    5     16.288      47      56.04
Xtend Memory                   Australia   2000    7          0      71       70.8
Xtend Memory                   Australia   2000    8      2.327      47     48.867
Xtend Memory                   Australia   2001    1      4.634      92     96.894
Xtend Memory                   Australia   2001    2     21.182     118    134.928
Xtend Memory                   Australia   2001    3     35.354      47     61.412
Xtend Memory                   Australia   2001    4     24.294     257     245.64
Xtend Memory                   Australia   2001    5      26.76      93     95.906
Xtend Memory                   Australia   2001    6     24.516      22     20.196
Xtend Memory                   Australia   2001    7      17.52      70     62.964
Xtend Memory                   Australia   2001    8     19.646      46     48.186
Xtend Memory                   Australia   2001    9     21.984      93     95.008

神奇的逆序求解(不知是怎麼求出來的)

按照邏輯來說,要先知道1才能知道2,但是下面不知道是怎麼求的。

SH@ prod> select product , country , year , week , inventory , sale , receipts from sales_fact 
  2  where country in ('Australia') and product = 'Xtend Memory' and week < 10
  3  model return updated rows
  4  partition by (product , country)
  5  dimension by (year , week)
  6  measures (0 inventory , sale , receipts)
  7  rules (
  8  inventory[year , week] order by year , week desc  
  9  = nvl(inventory[cv(year) , cv(week)-1] , 0 )
 10  - sale[cv(year) , cv(week)] 
 11  + receipts[cv(year) , cv(week)])
 12  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998    1       8.88      58      67.03
Xtend Memory                   Australia   1998    2      5.878      29     35.268
Xtend Memory                   Australia   1998    3      5.898      29     35.388
Xtend Memory                   Australia   1998    4    -11.796      29     17.694
Xtend Memory                   Australia   1998    5       5.96      30      35.76
Xtend Memory                   Australia   1998    6     -5.878      59     52.902
Xtend Memory                   Australia   1998    9      2.939      59     61.719
Xtend Memory                   Australia   1999    1      2.676      54     56.196
Xtend Memory                   Australia   1999    3       4.73      95      99.33
Xtend Memory                   Australia   1999    4          0      41       40.5
Xtend Memory                   Australia   1999    5      5.334      80     85.344
Xtend Memory                   Australia   1999    6      -4.05      41      36.45
Xtend Memory                   Australia   1999    8     -2.196     103    100.914
Xtend Memory                   Australia   1999    9     16.002      53     69.342
Xtend Memory                   Australia   2000    1    -11.675      47     35.025
Xtend Memory                   Australia   2000    3     11.602      93    105.012
Xtend Memory                   Australia   2000    4     -4.654      47     41.886
Xtend Memory                   Australia   2000    5       9.34      47      56.04
Xtend Memory                   Australia   2000    7          0      71       70.8
Xtend Memory                   Australia   2000    8      2.327      47     48.867
Xtend Memory                   Australia   2001    1      4.634      92     96.894
Xtend Memory                   Australia   2001    2     16.548     118    134.928
Xtend Memory                   Australia   2001    3     14.172      47     61.412
Xtend Memory                   Australia   2001    4     -11.06     257     245.64
Xtend Memory                   Australia   2001    5      2.466      93     95.906
Xtend Memory                   Australia   2001    6     -2.244      22     20.196
Xtend Memory                   Australia   2001    7     -6.996      70     62.964
Xtend Memory                   Australia   2001    8      2.126      46     48.186
Xtend Memory                   Australia   2001    9      2.338      93     95.008

29 rows selected.

多條規則的順序問題

下面的這條語句中,不同的順序求解出來的東西是不一樣的。因爲兩條規則有相關性。
順序求解

SH@ prod> select * from (
  2  select product , country , year , week , inventory , sale , receipts from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures (0 inventory , sale , receipts)
  8  rules sequential order(
  9  inventory[year , week] order by year , week
 10  = nvl(inventory[cv(year) , cv(week)-1] , 0 )
 11  - sale[cv(year) , cv(week)] 
 12  + receipts[cv(year) , cv(week)] ,
 13  receipts [ year in(2000 , 2001) , week in (51 , 52 , 53)] order by year , week 
 14  = receipts[cv(year) , cv(week)]*10 )
 15  order by product , country , year , week )
 16  where week > 50 ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998   51        .04      58     61.236
Xtend Memory                   Australia   1998   52      5.812      86     92.152
Xtend Memory                   Australia   1999   53     -2.705      27     24.345
Xtend Memory                   Australia   2000   52     -1.383      67     660.67
Xtend Memory                   Australia   2001   51       4.86     115     1102.8
Xtend Memory                   Australia   2001   52     14.116      23     323.96

6 rows selected.

讓Oracle自己去判斷順序。

SH@ prod> select * from (
  2  select product , country , year , week , inventory , sale , receipts from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures (0 inventory , sale , receipts)
  8  rules automatic order(
  9  inventory[year , week] order by year , week
 10  = nvl(inventory[cv(year) , cv(week)-1] , 0 )
 11  - sale[cv(year) , cv(week)] 
 12  + receipts[cv(year) , cv(week)] ,
 13  receipts [ year in(2000 , 2001) , week in (51 , 52 , 53)] order by year , week 
 14  = receipts[cv(year) , cv(week)]*10 )
 15  order by product , country , year , week )
 16  where week > 50 ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS
------------------------------ ---------- ----- ---- ---------- ------- ----------
Xtend Memory                   Australia   1998   51        .04      58     61.236
Xtend Memory                   Australia   1998   52      5.812      86     92.152
Xtend Memory                   Australia   1999   53     -2.705      27     24.345
Xtend Memory                   Australia   2000   52     593.22      67     660.67
Xtend Memory                   Australia   2001   51     997.38     115     1102.8
Xtend Memory                   Australia   2001   52     1298.2      23     323.96

Model中的聚合

下面語句中的avg_inventory[year, ANY] = avg(inventory)[cv(year) , week ],用ANY是因爲右側的表達式對於所有的week都會返回相同的值,所以沒必要重複計算,對於所有的week只需要計算一次就行了。Avg後面的[cv(year) , week ]表示聚合的範圍是這一年和所有周。

SH@ prod> select product , country , year , week , inventory ,avg_inventory , max_sale
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures (0 inventory , 0 avg_inventory , 0 max_sale , sale , receipts )
  8  rules automatic order(
  9  inventory[year , week] order by year , week
 10  = nvl(inventory[cv(year) , cv(week)-1] , 0 )
 11  - sale[cv(year) , cv(week)] 
 12  + receipts[cv(year) , cv(week)] ,
 13  avg_inventory[year, ANY] = avg(inventory)[cv(year) , week ] , 表示聚合範圍爲這一年的所有周,因爲這
 14  max_sale[year , ANY] = max(sale)[cv(year),week]
 15  )
 16  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY AVG_INVENTORY   MAX_SALE
------------------------------ ---------- ----- ---- ---------- ------------- ----------
Xtend Memory                   Australia   1998    1       8.88    -.72541667     172.56
Xtend Memory                   Australia   1998    2     14.758    -.72541667     172.56
Xtend Memory                   Australia   1998    3     20.656    -.72541667     172.56
Xtend Memory                   Australia   1998    4       8.86    -.72541667     172.56
Xtend Memory                   Australia   1998    5      14.82    -.72541667     172.56
Xtend Memory                   Australia   1998    6      8.942    -.72541667     172.56
Xtend Memory                   Australia   1998    9      2.939    -.72541667     172.56
Xtend Memory                   Australia   1998   10        .01    -.72541667     172.56
Xtend Memory                   Australia   1998   12      -14.9    -.72541667     172.56
Xtend Memory                   Australia   1998   14     11.756    -.72541667     172.56
Xtend Memory                   Australia   1998   15      5.878    -.72541667     172.56
Xtend Memory                   Australia   1998   17     11.756    -.72541667     172.56
Xtend Memory                   Australia   1998   18      8.817    -.72541667     172.56
Xtend Memory                   Australia   1998   19      2.919    -.72541667     172.56
Xtend Memory                   Australia   1998   21       2.98    -.72541667     172.56

指定次數的迭代

以下的語句中規則會迭代5次,ITERATION_NUMBER從0到4。

SH@ prod> select year , week , sale , sale_list 
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures ( cast(' ' as varchar2(50) ) sale_list , sale )
  8  rules iterate (5) (
  9  sale_list[year , week ] order by year , week =
 10  sale[cv(year) , cv(week) - ITERATION_NUMBER + 2] ||
 11  case when ITERATION_NUMBER = 0 then ' ' else ' , ' end ||
 12  sale_list[cv(year) , cv(week)]
 13  )
 14  order by year , week ;

 YEAR WEEK    SALE SALE_LIST
----- ---- ------- --------------------------------------------------
 1998    1      58  ,  , 58.15 , 29.39 , 29.49
 1998    2      29  , 58.15 , 29.39 , 29.49 , 29.49
 1998    3      29 58.15 , 29.39 , 29.49 , 29.49 , 29.8
 1998    4      29 29.39 , 29.49 , 29.49 , 29.8 , 58.78
 1998    5      30 29.49 , 29.49 , 29.8 , 58.78 ,
 1998    6      59 29.49 , 29.8 , 58.78 ,  ,
 1998    9      59  ,  , 58.78 , 117.76 ,
 1998   10     118  , 58.78 , 117.76 ,  , 59.6
 1998   12      60 117.76 ,  , 59.6 ,  , 58.78
 1998   14      59 59.6 ,  , 58.78 , 58.78 ,
 1998   15      59  , 58.78 , 58.78 ,  , 58.78
 1998   17      59 58.78 ,  , 58.78 , 117.56 , 58.98
 1998   18     118  , 58.78 , 117.56 , 58.98 ,
 1998   19      59 58.78 , 117.56 , 58.98 ,  , 59.6
 1998   21      60 58.98 ,  , 59.6 ,  , 117.56
 1998   23     118 59.6 ,  , 117.56 ,  ,
 1998   26     118  ,  , 117.56 , 57.52 , 57.72

用PRESENV解決空值的問題

上個例子的結果中有這樣的數據
58 , , 58.15 , 29.39 , 29.49
是因爲訪問了不存在的行,返回空值造成的。

用PRESENTV解決這個問題。
PRESENTV(t , v1 , v2) 如果單元格t存在,返回v1,如果不存在,返回v2。

SH@ prod> select year , week , sale , sale_list 
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures ( cast(' ' as varchar2(50) ) sale_list , sale )
  8  rules iterate (5) (
  9  sale_list[year , week ] order by year , week =
 10  presentv(sale[cv(year) , cv(week) - ITERATION_NUMBER + 2] ,
 11  sale[cv(year) , cv(week) - ITERATION_NUMBER + 2] ||
 12  case when ITERATION_NUMBER = 0 then ' ' else ' , ' end ||
 13  sale_list[cv(year) , cv(week)] ,
 14  sale_list[cv(year) , cv(week)]
 15  )
 16  )
 17  order by year , week ;

 YEAR WEEK    SALE SALE_LIST
----- ---- ------- --------------------------------------------------
 1998    1      58 58.15 , 29.39 , 29.49
 1998    2      29 58.15 , 29.39 , 29.49 , 29.49
 1998    3      29 58.15 , 29.39 , 29.49 , 29.49 , 29.8
 1998    4      29 29.39 , 29.49 , 29.49 , 29.8 , 58.78
 1998    5      30 29.49 , 29.49 , 29.8 , 58.78 ,
 1998    6      59 29.49 , 29.8 , 58.78 ,
 1998    9      59 58.78 , 117.76 ,
 1998   10     118 58.78 , 117.76 , 59.6
 1998   12      60 117.76 , 59.6 , 58.78
 1998   14      59 59.6 , 58.78 , 58.78 ,
 1998   15      59 58.78 , 58.78 , 58.78
 1998   17      59 58.78 , 58.78 , 117.56 , 58.98
 1998   18     118 58.78 , 117.56 , 58.98 ,
 1998   19      59 58.78 , 117.56 , 58.98 , 59.6
 1998   21      60 58.98 , 59.6 , 117.56
 1998   23     118 59.6 , 117.56 ,
 1998   26     118 117.56 , 57.52 , 57.72
 1998   27      58 117.56 , 57.52 , 57.72 , 57.72
 1998   28      58 117.56 , 57.52 , 57.72 , 57.72 ,
 1998   29      58 57.52 , 57.72 , 57.72 ,
 1998   34     115 115.44 , 57.52 ,
 1998   35      58 115.44 , 57.52 ,
 1998   38     116 115.84 , 115.84 , 57.52
 1998   39     116 115.84 , 115.84 , 57.52 , 58.32

PRESENTNNV(NOT NULL VALUE)

用法同PRESENTV,只是多了非空條件。
PRESENTNNV(t , v1 , v2) 如果單元格t存在且非空,返回v1,否則,返回v2。

查找表(參考表)

用REFERENCE關鍵字可以指定一個參考表。參考表可以查詢自其它的表。

SH@ prod> select year , week , sale , prod_list_price 
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  REFERENCE ref_prod on  引用如下的參考表
  6  ( select prod_name , max(prod_list_price) prod_list_price from products
  7  group by prod_name )
  8  dimension by (prod_name )  指定維度(自變量)
  9  measures(prod_list_price)  指定度得值(因變量)
 10  MAIN main_section
 11  partition by (product , country)   分區可以說是維度的維度
 12  dimension by (year , week)
 13  measures ( sale , receipts , 0 prod_list_price )
 14  rules (
 15  prod_list_price[year , week ] order by year , week 
 16  = ref_prod.prod_list_price[cv(product)]  參考表中給定一個維度值,會給出一個measure值。
 17  )
 18  order by year , week ;

 YEAR WEEK    SALE PROD_LIST_PRICE
----- ---- ------- ---------------
 1998    1      58           20.99
 1998    2      29           20.99
 1998    3      29           20.99
 1998    4      29           20.99
 1998    5      30           20.99
 1998    6      59           20.99
 1998    9      59           20.99
 1998   10     118           20.99
 1998   12      60           20.99
 1998   14      59           20.99
 1998   15      59           20.99
 1998   17      59           20.99
 1998   18     118           20.99
 1998   19      59           20.99
 1998   21      60           20.99
 1998   23     118           20.99
 1998   26     118           20.99
 1998   27      58           20.99
 1998   28      58           20.99
 1998   29      58           20.99
 1998   34     115           20.99
 1998   35      58           20.99
 1998   38     116           20.99
 1998   39     116           20.99
 1998   40      58           20.99
 1998   41      58           20.99
 1998   42     116           20.99
 1998   43      58           20.99
 1998   44      58           20.99
 1998   45      58           20.99
 1998   46      58           20.99
 1998   47      58           20.99

兩個參考表的情況

SH@ prod> select year , week , sale , prod_list_price , iso_code
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  REFERENCE ref_prod on
  6  ( select prod_name , max(prod_list_price) prod_list_price from products
  7  group by prod_name )
  8  dimension by (prod_name )
  9  measures(prod_list_price)
 10  REFERENCE ref_country on
 11  ( select country_name , country_iso_code from countries )
 12  dimension by (country_name )
 13  measures (country_iso_code)
 14  MAIN main_section
 15  partition by (product , country)
 16  dimension by (year , week)
 17  measures ( sale , receipts , 0 prod_list_price , cast(' ' as varchar2(5)) iso_code )  0表示度量值的默認值。
 18  rules (
 19  prod_list_price[year , week ] order by year , week 
 20  = ref_prod.prod_list_price[cv(product)] ,
 21  iso_code[year , week] order by year , week 
 22  = ref_country.country_iso_code [cv(country)]
 23  )
 24  order by year , week ;

      YEAR       WEEK       SALE PROD_LIST_PRICE ISO_C
---------- ---------- ---------- --------------- -----
      1998          1      58.15           20.99 AU
      1998          2      29.39           20.99 AU
      1998          3      29.49           20.99 AU
      1998          4      29.49           20.99 AU
      1998          5       29.8           20.99 AU
      1998          6      58.78           20.99 AU
      1998          9      58.78           20.99 AU
      1998         10     117.76           20.99 AU
      1998         12       59.6           20.99 AU
      1998         14      58.78           20.99 AU
      1998         15      58.78           20.99 AU
      1998         17      58.78           20.99 AU
      1998         18     117.56           20.99 AU
      1998         19      58.98           20.99 AU
      1998         21       59.6           20.99 AU
      1998         23     117.56           20.99 AU
      1998         26     117.56           20.99 AU
      1998         27      57.52           20.99 AU
      1998         28      57.72           20.99 AU
      1998         29      57.72           20.99 AU
      1998         34     115.44           20.99 AU
      1998         35      57.52           20.99 AU
      1998         38     115.84           20.99 AU
      1998         39     115.84           20.99 AU
      1998         40      57.52           20.99 AU
      1998         41      58.32           20.99 AU
      1998         42     115.84           20.99 AU

對於不存在的單元格的處理

默認的情況下(KEEP NAV)

SH@ prod> select product , country , year , week , sale 
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures(sale)
  8  rules sequential order (
  9  sale[2001 , 1] order by year , week = sale[2001 , 1] ,
 10  sale[2002 , 1] order by year , week = sale[2001 , 1] + sale[2002 , 1]
 11  )
 12  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK    SALE
------------------------------ ---------- ----- ---- -------
Xtend Memory                   Australia   2001    1      92
Xtend Memory                   Australia   2002    1

指定KEEP NAV (NOT AVAILABLE VALUE),訪問不存在的單元格時認爲其是不確定值NULL。

SH@ prod> select product , country , year , week , sale 
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model KEEP NAV return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures(sale)
  8  rules sequential order (
  9  sale[2001 , 1] order by year , week = sale[2001 , 1] ,
 10  sale[2002 , 1] order by year , week = sale[2001 , 1] + sale[2002 , 1]
 11  )
 12  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK    SALE
------------------------------ ---------- ----- ---- -------
Xtend Memory                   Australia   2001    1      92
Xtend Memory                   Australia   2002    1

指定IGNORE NAV,訪問不存在的單元格時相當於返回了0,而不是NULL(不確定值)。

SH@ prod> select product , country , year , week , sale 
  2  from sales_fact 
  3  where country in ('Australia') and product = 'Xtend Memory' 
  4  model IGNORE NAV return updated rows
  5  partition by (product , country)
  6  dimension by (year , week)
  7  measures(sale)
  8  rules sequential order (
  9  sale[2001 , 1] order by year , week = sale[2001 , 1] ,
 10  sale[2002 , 1] order by year , week = sale[2001 , 1] + sale[2002 , 1]
 11  )
 12  order by product , country , year , week ;

PRODUCT                        COUNTRY     YEAR WEEK    SALE
------------------------------ ---------- ----- ---- -------
Xtend Memory                   Australia   2001    1      92
Xtend Memory                   Australia   2002    1      92

Model子句的執行計劃

與分析函數類似,這裏只是多了一個SQL MODEL ACYCLIC(並不全都是這個)

SH@ prod> explain plan for
  2  select product , country , year , week , sale , receipts
  3  from sales_fact 
  4  where country in ('Australia') and product = 'Xtend Memory' 
  5  model IGNORE NAV return updated rows
  6  partition by (product , country)
  7  dimension by (year , week)
  8  measures( 0 inventory , sale , receipts )
  9  rules automatic order (
 10  inventory[year , week] order by year , week =
 11  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 12  - sale[cv(year) , cv(week)] +
 13  + receipts[cv(year) , cv(week)]
 14  )
 15  order by product , country , year , week ;

Explained.

SH@ prod> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 612713790

----------------------------------------------------------------------------------
| Id  | Operation           | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |            |   162 |  9072 |   310   (1)| 00:00:04 |
|   1 |  SORT ORDER BY      |            |   162 |  9072 |   310   (1)| 00:00:04 |
|   2 |   SQL MODEL ACYCLIC |            |   162 |  9072 |   310   (1)| 00:00:04 |
|*  3 |    TABLE ACCESS FULL| SALES_FACT |   162 |  9072 |   309   (1)| 00:00:04 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

15 rows selected.

SQL MODEL ACYCLIC FAST(只訪問指定的行時)

SH@ prod> explain plan for
  2  select product , country , year , week , sale_first_week 
  3  from sales_fact 
  4  where country in ('Australia') and product = 'Xtend Memory' 
  5  model IGNORE NAV return updated rows
  6  partition by (product , country)
  7  dimension by (year , week)
  8  measures( 0 sale_first_week , sale )
  9  rules automatic order (
 10  sale_first_week[2000 , 1] = 0.12*sale[2000 , 1]
 11  )
 12  order by product , country , year , week ;

Explained.

SH@ prod> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2162534578

--------------------------------------------------------------------------------------
| Id  | Operation               | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |            |   162 |  8100 |   310   (1)| 00:00:04 |
|   1 |  SORT ORDER BY          |            |   162 |  8100 |   310   (1)| 00:00:04 |
|   2 |   SQL MODEL ACYCLIC FAST|            |   162 |  8100 |   310   (1)| 00:00:04 |
|*  3 |    TABLE ACCESS FULL    | SALES_FACT |   162 |  8100 |   309   (1)| 00:00:04 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

15 rows selected.

SQL MODEL CYCLIC(沒有指定順序時)

SH@ prod> explain plan for
  2  select product , country , year , week , sale , receipts
  3  from sales_fact 
  4  where country in ('Australia') and product = 'Xtend Memory' 
  5  model return updated rows
  6  partition by (product , country)
  7  dimension by (year , week)
  8  measures( 0 inventory , sale , receipts )
  9  rules automatic order (
 10  inventory[year , week]  =
 11  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 12  - sale[cv(year) , cv(week)] +
 13  + receipts[cv(year) , cv(week)]
 14  )
 15  order by product , country , year , week ;

Explained.

SH@ prod> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1486878524

----------------------------------------------------------------------------------
| Id  | Operation           | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |            |   162 |  9072 |   310   (1)| 00:00:04 |
|   1 |  SORT ORDER BY      |            |   162 |  9072 |   310   (1)| 00:00:04 |
|   2 |   SQL MODEL CYCLIC  |            |   162 |  9072 |   310   (1)| 00:00:04 |
|*  3 |    TABLE ACCESS FULL| SALES_FACT |   162 |  9072 |   309   (1)| 00:00:04 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

15 rows selected.

SQL MODEL ORDERED(SEQUENTIAL的情況下)

SH@ prod> explain plan for
  2  select product , country , year , week , sale , receipts
  3  from sales_fact 
  4  where country in ('Australia') and product = 'Xtend Memory' 
  5  model return updated rows
  6  partition by (product , country)
  7  dimension by (year , week)
  8  measures( 0 inventory , sale , receipts )
  9  rules sequential order (
 10  inventory[year , week] order by year , week =
 11  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 12  - sale[cv(year) , cv(week)] +
 13  + receipts[cv(year) , cv(week)]
 14  )
 15  order by product , country , year , week ;

Explained.

SH@ prod> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3753083011

----------------------------------------------------------------------------------
| Id  | Operation           | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |            |   162 |  9072 |   310   (1)| 00:00:04 |
|   1 |  SORT ORDER BY      |            |   162 |  9072 |   310   (1)| 00:00:04 |
|   2 |   SQL MODEL ORDERED |            |   162 |  9072 |   310   (1)| 00:00:04 |
|*  3 |    TABLE ACCESS FULL| SALES_FACT |   162 |  9072 |   309   (1)| 00:00:04 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

15 rows selected.

謂詞的自動推進

下面的例子中,謂詞是作用在視圖外面的,但是卻發生了謂詞推進。
謂詞推進行原則:分區列上的謂詞可以安全的推進。因爲數據不會跨分區引用。

SH@ prod> explain plan for
  2  select * from (
  3  select product , country , year , week , sale , receipts
  4  from sales_fact 
  5  model return updated rows
  6  partition by (product , country)
  7  dimension by (year , week)
  8  measures( 0 inventory , sale , receipts )
  9  rules automatic order (
 10  inventory[year , week] =
 11  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 12  - sale[cv(year) , cv(week)] +
 13  + receipts[cv(year) , cv(week)]
 14  )
 15  )
 16  where country in ('Australia') and product = 'Xtend Memory' 
 17  order by product , country , year , week ;

Explained.

SH@ prod> SELECT * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1551402430

-----------------------------------------------------------------------------------
| Id  | Operation            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |            |   162 | 16362 |   310   (1)| 00:00:04 |
|   1 |  SORT ORDER BY       |            |   162 | 16362 |   310   (1)| 00:00:04 |
|   2 |   VIEW               |            |   162 | 16362 |   309   (1)| 00:00:04 |
|   3 |    SQL MODEL CYCLIC  |            |   162 |  9072 |            |          |
|*  4 |     TABLE ACCESS FULL| SALES_FACT |   162 |  9072 |   309   (1)| 00:00:04 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

16 rows selected.

不能推進行的謂詞(作用在維度列上的謂詞)

下面的例子中Oracle自動對能推進的謂詞和不能推進的謂詞進行了拆分。
維度列上的謂詞推進不安全,因爲被排除的維度值可能被其它的維度值引用。

SH@ prod> explain plan for
  2  select * from (
  3  select product , country , year , week , sale , receipts
  4  from sales_fact 
  5  model return updated rows
  6  partition by (product , country)
  7  dimension by (year , week)
  8  measures( 0 inventory , sale , receipts )
  9  rules automatic order (
 10  inventory[year , week] =
 11  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 12  - sale[cv(year) , cv(week)] +
 13  + receipts[cv(year) , cv(week)]
 14  )
 15  )
 16  where country in ('Australia') and product = 'Xtend Memory' 
 17  and year = 2000
 18  order by product , country , year , week ;

Explained.

SH@ prod> SELECT * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1551402430

-----------------------------------------------------------------------------------
| Id  | Operation            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |            |   162 | 16362 |   310   (1)| 00:00:04 |
|   1 |  SORT ORDER BY       |            |   162 | 16362 |   310   (1)| 00:00:04 |
|*  2 |   VIEW               |            |   162 | 16362 |   309   (1)| 00:00:04 |
|   3 |    SQL MODEL CYCLIC  |            |   162 |  9072 |            |          |
|*  4 |     TABLE ACCESS FULL| SALES_FACT |   162 |  9072 |   309   (1)| 00:00:04 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("YEAR"=2000)
   4 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

17 rows selected.

爲包含Model的查詢建立物化視圖

注意:這種物化視圖不能設置成fast incremental refresh。

SH@ prod> create materialized view mv_model_inventory 
  2  enable query rewrite as 
  3  select product , country , year , week , sale , receipts
  4  from sales_fact 
  5  where country in ('Australia') and product = 'Xtend Memory' 
  6  model return updated rows
  7  partition by (product , country)
  8  dimension by (year , week)
  9  measures( 0 inventory , sale , receipts )
 10  rules sequential order (
 11  inventory[year , week] order by year , week =
 12  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 13  - sale[cv(year) , cv(week)] +
 14  + receipts[cv(year) , cv(week)]
 15  );

Materialized view created.

SH@ prod> 
SH@ prod> explain plan for
  2  select * from (
  3  select product , country , year , week , sale , receipts
  4  from sales_fact 
  5  where country in ('Australia') and product = 'Xtend Memory' 
  6  model return updated rows
  7  partition by (product , country)
  8  dimension by (year , week)
  9  measures( 0 inventory , sale , receipts )
 10  rules sequential order (
 11  inventory[year , week] order by year , week =
 12  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 13  - sale[cv(year) , cv(week)] +
 14  + receipts[cv(year) , cv(week)]
 15  )
 16  )
 17  where country in ('Australia') and product = 'Xtend Memory' 
 18  order by product , country , year , week ;

Explained.

SH@ prod> SELECT * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2344724570

----------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                    |   159 | 16059 |     4  (25)| 00:00:01 |
|   1 |  SORT ORDER BY                |                    |   159 | 16059 |     4  (25)| 00:00:01 |
|*  2 |   MAT_VIEW REWRITE ACCESS FULL| MV_MODEL_INVENTORY |   159 | 16059 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("MV_MODEL_INVENTORY"."COUNTRY"='Australia' AND
              "MV_MODEL_INVENTORY"."PRODUCT"='Xtend Memory')

Note
-----
   - dynamic sampling used for this statement (level=2)

19 rows selected.

Model子句的並行

SH@ prod> explain plan for
  2  select /*+ parallel(sf 4) */
  3  product , country , year , week , sale , receipts
  4  from sales_fact sf
  5  where country in ('Australia') and product = 'Xtend Memory' 
  6  model return updated rows
  7  partition by (product , country)
  8  dimension by (year , week)
  9  measures( 0 inventory , sale , receipts )
 10  rules automatic order (
 11  inventory[year , week] order by year , week =
 12  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 13  - sale[cv(year) , cv(week)] +
 14  + receipts[cv(year) , cv(week)]
 15  );

Explained.

SH@ prod> SELECT * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2789944137

--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |            |   162 |  9072 |    86   (0)| 00:00:02 |        |      |            |
|   1 |  PX COORDINATOR          |            |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)    | :TQ10001   |   162 |  9072 |            |          |  Q1,01 | P->S | QC (RAND)  |
|   3 |    BUFFER SORT           |            |   162 |  9072 |            |          |  Q1,01 | PCWP |            |
|   4 |     SQL MODEL ACYCLIC    |            |   162 |  9072 |            |          |  Q1,01 | PCWP |            |
|   5 |      PX RECEIVE          |            |   162 |  9072 |    86   (0)| 00:00:02 |  Q1,01 | PCWP |            |
|   6 |       PX SEND HASH       | :TQ10000   |   162 |  9072 |    86   (0)| 00:00:02 |  Q1,00 | P->P | HASH       |
|   7 |        PX BLOCK ITERATOR |            |   162 |  9072 |    86   (0)| 00:00:02 |  Q1,00 | PCWC |            |
|*  8 |         TABLE ACCESS FULL| SALES_FACT |   162 |  9072 |    86   (0)| 00:00:02 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   8 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

20 rows selected.

Model子句中的分區剪裁

如果Model子句中的分區列與表的分區鍵相匹配的話,那麼就可以用到分區剪裁來優化。

Model子句的子查詢因子化

SH@ prod> with t1 as 
  2  (
  3  select product , country , year , week , inventory , sale , receipts
  4  from sales_fact sf
  5  where country in ('Australia') and product = 'Xtend Memory' 
  6  model return updated rows
  7  partition by (product , country)
  8  dimension by (year , week)
  9  measures( 0 inventory , sale , receipts )
 10  rules automatic order (
 11  inventory[year , week] order by year , week =
 12  nvl(inventory[cv(year) , cv(week) -1 ] , 0)
 13  - sale[cv(year) , cv(week)] +
 14  + receipts[cv(year) , cv(week)]
 15  )
 16  )
 17  select product , country , year , week , inventory , sale , receipts , prev_sale 
 18  from t1
 19  model return updated rows
 20  partition by ( product , country )
 21  dimension by ( year , week )
 22  measures ( inventory , sale , receipts , 0 prev_sale )
 23  rules sequential order (
 24  prev_sale[year , week ] order by year , week =
 25  nvl(sale[cv(year)-1 , cv(week)] , 0)
 26  )
 27  order by 1 , 2 , 3 , 4 ;

PRODUCT                        COUNTRY     YEAR WEEK  INVENTORY    SALE   RECEIPTS  PREV_SALE
------------------------------ ---------- ----- ---- ---------- ------- ---------- ----------
Xtend Memory                   Australia   1998    1       8.88      58      67.03          0
Xtend Memory                   Australia   1998    2     14.758      29     35.268          0
Xtend Memory                   Australia   1998    3     20.656      29     35.388          0
Xtend Memory                   Australia   1998    4       8.86      29     17.694          0
Xtend Memory                   Australia   1998    5      14.82      30      35.76          0
Xtend Memory                   Australia   1998    6      8.942      59     52.902          0
Xtend Memory                   Australia   1998    9      2.939      59     61.719          0
Xtend Memory                   Australia   1998   10        .01     118    114.831          0
Xtend Memory                   Australia   1998   12      -14.9      60       44.7          0
Xtend Memory                   Australia   1998   14     11.756      59     70.536          0
Xtend Memory                   Australia   1998   15      5.878      59     52.902          0
Xtend Memory                   Australia   1998   17     11.756      59     70.536          0
Xtend Memory                   Australia   1998   18      8.817     118    114.621          0
Xtend Memory                   Australia   1998   19      2.919      59     53.082          0
Xtend Memory                   Australia   1998   21       2.98      60      62.58          0
Xtend Memory                   Australia   1998   23    -11.756     118    105.804          0
Xtend Memory                   Australia   1998   26     11.756     118    129.316          0
Xtend Memory                   Australia   1998   27     14.632      58     60.396          0
Xtend Memory                   Australia   1998   28       .202      58      43.29          0
Xtend Memory                   Australia   1998   29    -14.228      58      43.29          0
Xtend Memory                   Australia   1998   34     -2.886     115    112.554          0
Xtend Memory                   Australia   1998   35     -8.638      58     51.768          0
Xtend Memory                   Australia   1998   38    -11.464     116    104.376          0
Xtend Memory                   Australia   1998   39     -5.792     116    121.512          0
Xtend Memory                   Australia   1998   40    -11.544      58     51.768          0
Xtend Memory                   Australia   1998   41    -17.376      58     52.488          0
Xtend Memory                   Australia   1998   42     -5.832     116    127.384          0
Xtend Memory                   Australia   1998   43    -11.584      58     51.768          0
Xtend Memory                   Australia   1998   44     -8.708      58     60.396          0
Xtend Memory                   Australia   1998   45    -23.088      58      43.14          0
Xtend Memory                   Australia   1998   46    -20.212      58     60.396          0
Xtend Memory                   Australia   1998   47    -17.326      58     60.606          0
Xtend Memory                   Australia   1998   48      5.682     173    195.568          0
Xtend Memory                   Australia   1998   50     -2.876      29     25.884          0
Xtend Memory                   Australia   1998   51        .04      58     61.236          0
Xtend Memory                   Australia   1998   52      5.812      86     92.152          0
Xtend Memory                   Australia   1999    1      2.676      54     56.196      58.15
Xtend Memory                   Australia   1999    3       4.73      95      99.33      29.49
Xtend Memory                   Australia   1999    4       4.73      41       40.5      29.49
Xtend Memory                   Australia   1999    5     10.064      80     85.344       29.8
Xtend Memory                   Australia   1999    6      6.014      41      36.45      58.78
Xtend Memory                   Australia   1999    8     -2.196     103    100.914          0
Xtend Memory                   Australia   1999    9     13.806      53     69.342      58.78
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章