CV() in Model clause

Hi,
Although this query returns 6 rows of data (2 rows having data, and rest of the rows are having NULL values), where as my requirement is to to get the following output:
RUN_SEQ
USAGE_PERIOD_START_DATE_D
USAGE_PERIOD_END_DATE_D
1
01-Jan-13
30-Jan-13
2
31-Jan-13
01-Mar-13
3
02-Mar-13
31-Mar-13
4
01-Apr-13
30-Apr-13
5
01-May-13
30-May-13
6
31-May-13
29-Jun-13
select RUN_SEQ, USAGE_PERIOD_START_DATE_D, USAGE_PERIOD_END_DATE_D
  from dual
model
   dimension by (1 as idx)
       MEASURES (
        1 as RUN_SEQ,
        TO_DATE('20130101','YYYYMMDD') AS USAGE_PERIOD_START_DATE_D,
        TO_DATE('20130101','YYYYMMDD')+29 AS USAGE_PERIOD_END_DATE_D
   rules upsert all (
      RUN_SEQ[for idx from 2 to 6 increment 1] = RUN_SEQ[cv()-1]+1,
      USAGE_PERIOD_START_DATE_D[for idx from 2 to 6 increment 1] = USAGE_PERIOD_END_DATE_D[cv()-1]+1,
      USAGE_PERIOD_END_DATE_D[for idx from 2 to 6 increment 1] = USAGE_PERIOD_START_DATE_D[cv()]+29
order by idx;
Could anyone please suggest where am I going wrong.
Thanks & Regards,
Pawan

You may also control the "rules-flow" by yourself and rewrite it as an iterative model
select RUN_SEQ, USAGE_PERIOD_START_DATE_D, USAGE_PERIOD_END_DATE_D
  from dual
model
   dimension by (1 as idx)
       MEASURES (
        1 as RUN_SEQ,
        TO_DATE('20130101','YYYYMMDD') AS USAGE_PERIOD_START_DATE_D,
        TO_DATE('20130101','YYYYMMDD')+29 AS USAGE_PERIOD_END_DATE_D
   rules iterate (5) (
      RUN_SEQ[iteration_number+2] = RUN_SEQ[iteration_number+1] + 1,
      USAGE_PERIOD_START_DATE_D[iteration_number+2] = USAGE_PERIOD_END_DATE_D[iteration_number+1]+1,
      USAGE_PERIOD_END_DATE_D[iteration_number+2] = USAGE_PERIOD_START_DATE_D[iteration_number+2]+29
order by idx;

Similar Messages

  • Avoiding null and duplicate values using model clause

    Hi,
    I am trying to use model clause to get comma seperated list of data : following is the scenario:
    testuser>select * from test1;
    ID VALUE
    1 Value1
    2 Value2
    3 Value3
    4 Value4
    5 Value4
    6
    7 value5
    8
    8 rows selected.
    the query I have is:
    testuser>with src as (
    2 select distinct id,value
    3 from test1
    4 ),
    5 t as (
    6 select distinct substr(value,2) value
    7 from src
    8 model
    9 ignore nav
    10 dimension by (id)
    11 measures (cast(value as varchar2(100)) value)
    12 rules
    13 (
    14 value[any] order by id =
    15 value[cv()-1] || ',' || value[cv()]
    16 )
    17 )
    18 select max(value) oneline
    19 from t;
    ONELINE
    Value1,Value2,Value3,Value4,Value4,,value5,
    what I find is that this query has duplicate value and null (',,') coming in as data has null and duplicate value. Is there a way i can avoid the null and the duplicate values in the query output?
    thanks,
    Edited by: orausern on Feb 19, 2010 5:05 AM

    Hi,
    Try this code.
    with
    t as ( select substr(value,2)value,ind
            from test1
            model
            ignore nav
            dimension by (id)
            measures (cast(value as varchar2(100)) value, 0 ind)
            rules
            ( ind[any]=  instr(value[cv()-1],value[cv()]),
            value[any] order by id = value[cv()-1] || CASE WHEN value[cv()] IS NOT NULL
                                               and ind[cv()]=0     THEN ',' || value[cv()] END      
    select max(value) oneline
    from t;
    SQL> select * from test1;
            ID VALUE
             1 Value1
             2 Value2
             3 Value3
             4 Value4
             5 Value4
             6
             7 value5
             8
    8 ligne(s) sélectionnée(s).
    SQL> with
      2   t as ( select substr(value,2)value,ind
      3          from test1
      4          model
      5          ignore nav
      6          dimension by (id)
      7          measures (cast(value as varchar2(100)) value, 0 ind)
      8          rules
      9          ( ind[any]=  instr(value[cv()-1],value[cv()]),
    10          value[any] order by id = value[cv()-1] || CASE WHEN value[cv()] IS NOT NULL
    11                                             and ind[cv()]=0     THEN ',' || value[cv()] END 
    12          )
    13        )
    14   select max(value) oneline
    15   from t;
    ONELINE
    Value1,Value2,Value3,Value4,value5
    SQL>

  • Query help with Model clause

    Hi Gurus,
    Can someone please help me out.
    I've a below tables.
    1) tbl_link --> this table contains information at profile level
    2) tbl_summary --> this table contains summary at parent profile level derived from tbl_link table
    One parent profile contains multiple child profiles and each child profile links to a code (which is B, W, G or P) and the code is linked to a category (i.e. ONL and OFL). In this case code B is linked to category 'ONL' and codes W,G,P linked to OFL category.
    ONL category needs 100 points. If it don't have enough points then i need to borrow from OFL category which i'm doing and populating into tbl_summary table at parent profile level.
    Now i need to insert data into tbl_link table at profile level with howmany points used, expired based on tbl_summary table. Rule is at the end of month if we add points for each profile in tbl_link table it should come as 0.
    with
    tbl_SUMMARY as
    select 1 as ppid,'ONL' as catgcode, 53 as earned_points,47 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
    union
    select 1 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,176 CERT_POINTS,76 DISCARD_POINTS,100 used from dual
    union
    select 2 as ppid,'ONL' as catgcode, 39 as earned_points,61 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
    union
    select 2 as ppid,'OFL' as catgcode, 90 as earned_points,0 BORROWED_POINTS,29 CERT_POINTS,29 DISCARD_POINTS,100 used from dual
    union
    select 3 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
    union
    select 3 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,223 CERT_POINTS,23 DISCARD_POINTS,200 used from dual
    union
    select 4 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
    union
    select 4 as ppid,'OFL' as catgcode, 169 as earned_points,0 BORROWED_POINTS,169 CERT_POINTS,69 DISCARD_POINTS,100 used from dual
    tbl_link as
    select 1 as ppid,1 as pid, 'B' as code,'ONL' as catgcode, 53 as earned_points from dual
    union
    select 1 as ppid,12 as pid, 'W' as code,'OFL' as catgcode, 26 as earned_points from dual
    union
    select 1 as ppid,13 as pid, 'G' as code,'OFL' as catgcode, 87 as earned_points from dual
    union
    select 1 as ppid,14 as pid, 'P' as code,'OFL' as catgcode, 110 as earned_points from dual
    union
    select 2 as ppid,2 as pid, 'B' as code,'ONL' as catgcode, 39 as earned_points from dual
    union
    select 2 as ppid,22 as pid, 'W' ,'OFL' as catgcode, 30 as earned_points from dual
    union
    select 2 as ppid,23 as pid, 'G' ,'OFL' as catgcode, 29 as earned_points from dual
    union
    select 2 as ppid,24 as pid, 'P' ,'OFL' as catgcode, 31 as earned_points from dual
    union
    select 3 as ppid,3 as pid, 'B' as code,'ONL' as tier_catgcode, 109 as earned_points from dual
    union
    select 3 as ppid,32 as pid, 'W' ,'OFL' , 26 as earned_points from dual
    union
    select 3 as ppid,33 as pid, 'G' ,'OFL', 87 as earned_points from dual
    union
    select 3 as ppid,34 as pid, 'P' ,'OFL' , 110 as earned_points from dual
    union
    select 4 as ppid,4 as pid, 'B' as code,'ONL' as catgcode, 109 as earned_points from dual
    union
    select 4 as ppid,42 as pid, 'W' as code,'OFL' , 26 as earned_points from dual
    union
    select 4 as ppid,43 as pid, 'G' as code,'OFL' , 87 as earned_points from dual
    union
    select 4 as ppid,44 as pid, 'P' as code,'OFL' , 56 as earned_points from dual
    final (PARENT_PROFILE_ID,PROFILE_ID,catgcode,EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED)
    as (
    select A.PPID PARENT_PROFILE_ID,B.PID PROFILE_ID,A.catgcode,B.EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED
    from tbl_SUMMARY a,tbl_link b where a.ppid=b.ppid AND A.catgcode=B.catgcode
    ORDER BY PROFILE_ID
    select * from final order by 1;
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED
    1                  1           ONL       53             47               100          0               100
    1                  14          OFL       110            0                176          76              100
    1                  13          OFL       87             0                176          76              100
    1                  12          OFL       26             0                176          76              100
    2                  2           ONL       39             61               100          0               100
    2                  24          OFL       31             0                29           29              100
    2                  23          OFL       29             0                29           29              100
    2                  22          OFL       30             0                29           29              100
    3                  32          OFL       26             0                223          23              200
    3                  33          OFL       87             0                223          23              200
    3                  34          OFL       110            0                223          23              200
    3                  3           ONL       109            0                109          9               100
    4                  42          OFL       26             0                169          69              100
    4                  43          OFL       87             0                169          69              100
    4                  44          OFL       56             0                169          69              100
    4                  4           ONL       109            0                109          9               100
    Need Output as below :
    For parent profile 1, whatever i mentioned above is not correct. Borrowed 47 points from OFL to ONL to make ONL and also from OFL category has 176 points remaining after lending to ONL and using only 100 points, remaining 76 points are discarded. Need to deduct these 76 points also from child profiles. Output will be as below.
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    1                  1           ONL       53             47               100          0               100   -53       0
    1                  12          OFL       26             0                176          76              100   -26       0
    1                  13          OFL       87             0                176          76              100   -74       -13
    1                  14          OFL       110            0                176          76              100   -47       -63
    For parent profile id 2 --> ONL category has 39 points, so borrowed 61 points from OFL category to make ONL points 100.
                                Now need to populate tbl_link table at child profile level (i.e. child profiles 22,23,24).
    Borrowed 61 points from OFL and need to deduct this points from the profile which has highest earned points, in this case deduct from profile 24 which has 31 points, from profile 22 which has 30 points. Need output like below
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    2                  2           ONL       39             61               100          0               100   -39       0
    2                  22          OFL       30             0                29           29              100   -30       0
    2                  23          OFL       29             0                29           29              100   0         -29
    2                  24          OFL       31             0                29           29              100   -31       0
    For parent profile id 3 --> ONL category has 109 points, so no need to borrow points from OFL category
                                Now need to populate tbl_link table at child profile level (i.e. child profiles 32,33,34).
    in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 223 points total. need only 200 points (i.e. mutiple of 100) for our process, 23 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 34. Output :
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    3                  3           ONL       109            0                109          9               100   -100      -9
    3                  32          OFL       26             0                223          23              200   -26       0
    3                  33          OFL       87             0                223          23              200   -87       0
    3                  34          OFL       110            0                223          23              200   -87       -23
    For parent profile id 4 --> ONL category has 109 points, so no need to borrow points from OFL category
                                Now need to populate tbl_link table at child profile level (i.e. child profiles 42,43,44).
    in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 169 points total. need only 100 points (i.e. mutiple of 100) for our process, 69 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 43. Output :
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    4                  4           ONL       109            0                109          9               100   100       9
    4                  42          OFL       26             0                169          69              100   -26       0
    4                  43          OFL       87             0                169          69              100   -18       -69
    4                  44          OFL       56             0                169          69              100   -56       0
    Can someone help with the query. I googled about looping in sql and came to know that Oracle has a feature MODEL to loop in SQL, but i don't have idea on using MODEL clause.
    Appreciate your help!
    Thanks
    Sri

    Hi Gurus,
    Can someone please help me out.
    I've a below tables.
    1) tbl_link --> this table contains information at profile level
    2) tbl_summary --> this table contains summary at parent profile level derived from tbl_link table
    One parent profile contains multiple child profiles and each child profile links to a code (which is B, W, G or P) and the code is linked to a category (i.e. ONL and OFL). In this case code B is linked to category 'ONL' and codes W,G,P linked to OFL category.
    ONL category needs 100 points. If it don't have enough points then i need to borrow from OFL category which i'm doing and populating into tbl_summary table at parent profile level.
    Now i need to insert data into tbl_link table at profile level with howmany points used, expired based on tbl_summary table. Rule is at the end of month if we add points for each profile in tbl_link table it should come as 0.
    with
    tbl_SUMMARY as
    select 1 as ppid,'ONL' as catgcode, 53 as earned_points,47 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
    union
    select 1 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,176 CERT_POINTS,76 DISCARD_POINTS,100 used from dual
    union
    select 2 as ppid,'ONL' as catgcode, 39 as earned_points,61 BORROWED_POINTS,100 CERT_POINTS,0 DISCARD_POINTS,100 used from dual
    union
    select 2 as ppid,'OFL' as catgcode, 90 as earned_points,0 BORROWED_POINTS,29 CERT_POINTS,29 DISCARD_POINTS,100 used from dual
    union
    select 3 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
    union
    select 3 as ppid,'OFL' as catgcode, 223 as earned_points,0 BORROWED_POINTS,223 CERT_POINTS,23 DISCARD_POINTS,200 used from dual
    union
    select 4 as ppid,'ONL' as catgcode, 109 as earned_points,0 BORROWED_POINTS,109 CERT_POINTS,9 DISCARD_POINTS,100 used from dual
    union
    select 4 as ppid,'OFL' as catgcode, 169 as earned_points,0 BORROWED_POINTS,169 CERT_POINTS,69 DISCARD_POINTS,100 used from dual
    tbl_link as
    select 1 as ppid,1 as pid, 'B' as code,'ONL' as catgcode, 53 as earned_points from dual
    union
    select 1 as ppid,12 as pid, 'W' as code,'OFL' as catgcode, 26 as earned_points from dual
    union
    select 1 as ppid,13 as pid, 'G' as code,'OFL' as catgcode, 87 as earned_points from dual
    union
    select 1 as ppid,14 as pid, 'P' as code,'OFL' as catgcode, 110 as earned_points from dual
    union
    select 2 as ppid,2 as pid, 'B' as code,'ONL' as catgcode, 39 as earned_points from dual
    union
    select 2 as ppid,22 as pid, 'W' ,'OFL' as catgcode, 30 as earned_points from dual
    union
    select 2 as ppid,23 as pid, 'G' ,'OFL' as catgcode, 29 as earned_points from dual
    union
    select 2 as ppid,24 as pid, 'P' ,'OFL' as catgcode, 31 as earned_points from dual
    union
    select 3 as ppid,3 as pid, 'B' as code,'ONL' as tier_catgcode, 109 as earned_points from dual
    union
    select 3 as ppid,32 as pid, 'W' ,'OFL' , 26 as earned_points from dual
    union
    select 3 as ppid,33 as pid, 'G' ,'OFL', 87 as earned_points from dual
    union
    select 3 as ppid,34 as pid, 'P' ,'OFL' , 110 as earned_points from dual
    union
    select 4 as ppid,4 as pid, 'B' as code,'ONL' as catgcode, 109 as earned_points from dual
    union
    select 4 as ppid,42 as pid, 'W' as code,'OFL' , 26 as earned_points from dual
    union
    select 4 as ppid,43 as pid, 'G' as code,'OFL' , 87 as earned_points from dual
    union
    select 4 as ppid,44 as pid, 'P' as code,'OFL' , 56 as earned_points from dual
    final (PARENT_PROFILE_ID,PROFILE_ID,catgcode,EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED)
    as (
    select A.PPID PARENT_PROFILE_ID,B.PID PROFILE_ID,A.catgcode,B.EARNED_POINTS,BORROWED_POINTS,CERT_POINTS,DISCARD_POINTS,USED
    from tbl_SUMMARY a,tbl_link b where a.ppid=b.ppid AND A.catgcode=B.catgcode
    ORDER BY PROFILE_ID
    select * from final order by 1;
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED
    1                  1           ONL       53             47               100          0               100
    1                  14          OFL       110            0                176          76              100
    1                  13          OFL       87             0                176          76              100
    1                  12          OFL       26             0                176          76              100
    2                  2           ONL       39             61               100          0               100
    2                  24          OFL       31             0                29           29              100
    2                  23          OFL       29             0                29           29              100
    2                  22          OFL       30             0                29           29              100
    3                  32          OFL       26             0                223          23              200
    3                  33          OFL       87             0                223          23              200
    3                  34          OFL       110            0                223          23              200
    3                  3           ONL       109            0                109          9               100
    4                  42          OFL       26             0                169          69              100
    4                  43          OFL       87             0                169          69              100
    4                  44          OFL       56             0                169          69              100
    4                  4           ONL       109            0                109          9               100
    Need Output as below :
    For parent profile 1, whatever i mentioned above is not correct. Borrowed 47 points from OFL to ONL to make ONL and also from OFL category has 176 points remaining after lending to ONL and using only 100 points, remaining 76 points are discarded. Need to deduct these 76 points also from child profiles. Output will be as below.
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    1                  1           ONL       53             47               100          0               100   -53       0
    1                  12          OFL       26             0                176          76              100   -26       0
    1                  13          OFL       87             0                176          76              100   -74       -13
    1                  14          OFL       110            0                176          76              100   -47       -63
    For parent profile id 2 --> ONL category has 39 points, so borrowed 61 points from OFL category to make ONL points 100.
                                Now need to populate tbl_link table at child profile level (i.e. child profiles 22,23,24).
    Borrowed 61 points from OFL and need to deduct this points from the profile which has highest earned points, in this case deduct from profile 24 which has 31 points, from profile 22 which has 30 points. Need output like below
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    2                  2           ONL       39             61               100          0               100   -39       0
    2                  22          OFL       30             0                29           29              100   -30       0
    2                  23          OFL       29             0                29           29              100   0         -29
    2                  24          OFL       31             0                29           29              100   -31       0
    For parent profile id 3 --> ONL category has 109 points, so no need to borrow points from OFL category
                                Now need to populate tbl_link table at child profile level (i.e. child profiles 32,33,34).
    in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 223 points total. need only 200 points (i.e. mutiple of 100) for our process, 23 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 34. Output :
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    3                  3           ONL       109            0                109          9               100   -100      -9
    3                  32          OFL       26             0                223          23              200   -26       0
    3                  33          OFL       87             0                223          23              200   -87       0
    3                  34          OFL       110            0                223          23              200   -87       -23
    For parent profile id 4 --> ONL category has 109 points, so no need to borrow points from OFL category
                                Now need to populate tbl_link table at child profile level (i.e. child profiles 42,43,44).
    in this case ONL has 100 points, so move the remaining 9 points will be expired. OFL category has 169 points total. need only 100 points (i.e. mutiple of 100) for our process, 69 points will be expired and has to deduct from the profile which has highest earned points, in this case from profile 43. Output :
    PARENT_PROFILE_ID  PROFILE_ID  CATGCODE  EARNED_POINTS  BORROWED_POINTS  CERT_POINTS  DISCARD_POINTS  USED  BURN_PTS  EXPIRE_PTS
    4                  4           ONL       109            0                109          9               100   100       9
    4                  42          OFL       26             0                169          69              100   -26       0
    4                  43          OFL       87             0                169          69              100   -18       -69
    4                  44          OFL       56             0                169          69              100   -56       0
    Can someone help with the query. I googled about looping in sql and came to know that Oracle has a feature MODEL to loop in SQL, but i don't have idea on using MODEL clause.
    Appreciate your help!
    Thanks
    Sri

  • Help with SQL MODEL Clause

    I have the privilege of performing a very tedious task.
    We have some home grown regular expressions in our company. I now need to expand these regular expressions.
    Samples:
    a = 0-3
    b = Null, 0, 1
    Expression: Meaning
    1:5: 1,2,3,4,5
    1a: 10, 11, 12, 13
    1b: 1, 10, 11
    1[2,3]ab: 120, 1200, 1201, ....
    It get's even more inetersting because there is a possibility of 1[2,3]a.ab
    I have created two base queries to aid me in my quest. I am using the SQL MODEL clause to solve this problem. I pretty confident that I should be able to convert evrything into a range and the use one of the MODEL clause listed below.
    My only confusion is how do I INCREMENT dynamically. The INCREMENT seems to be a constant in both a FOR and ITERATE statement. I need to figure a way to increment with .01, .1, etc.
    Any help will be greatly appreciated.
    CODE:
    Reference:          http://www.sqlsnippets.com/en/topic-11663.html
    Objective:          Expand a range with ITERATE
    WITH t AS
    (SELECT '2:4' pt
    FROM DUAL
    UNION ALL
    SELECT '6:9' pt
    FROM DUAL)
    SELECT pt AS code_expression
    -- , KEY
    -- , min_key
    -- , max_key
    , m_1 AS code
    FROM t
    MODEL
    PARTITION BY (pt)
    DIMENSION BY ( 0 AS KEY )
    MEASURES (
                        0 AS m_1,
                        TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key,
                        TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key               
    RULES
    -- UPSERT
    ITERATE (100000) UNTIL ( ITERATION_NUMBER = max_key[0] - min_key[0] )
    m_1[ITERATION_NUMBER] = min_key[0] + ITERATION_NUMBER
    ORDER BY pt, m_1
    Explanation:
    Line numbers are based on the assupmtion that "WITH t AS" starts at line 5.
    If you need detailed information regarding the MODEL clause please refer to
    the Refrence site stated above or read some documentation.
    Partition-
    Line 18:     PARTITION BY (pt)
                   This will make sure that each "KEY" will start at 0 for each value of pt.
    Dimension-
    Line 19:     DIMENSION BY ( 0 AS KEY )     
                   This is necessary for the refrences max_key[0], and min_key[0] to work.
    Measures-
    Line 21:      0 AS m_1
                   A space holder for new values.
    Line 22:     TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key
                   The result is '1' for '1:5'.
    Line 23:     TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key                                        
                   The result is '5' for '1:5'.
    Rules-
    Line 26:     UPSERT
                   This makes it possible for new rows to be created.
    Line 27:     ITERATE (100000) UNTIL ( ITERATION_NUMBER = max_key[0] - min_key[0] )
                   This reads ITERATE 100000 times or UNTIL the ITERATION_NUMBER = max_key[0] - min_key[0]
                   which would be 4 for '1:5', but since the ITERATION_NUMBER starts at 0, whatever follows
                   is repaeted 5 times.
    Line 29:     m_1[ITERATION_NUMBER] = min_key[0] + ITERATION_NUMBER
                   m_1[ITERATION_NUMBER] means m_1[Value of Dimension KEY].
                   Thus for each row of KEY the m_1 is min_key[0] + ITERATION_NUMBER.
    Reference:          http://www.sqlsnippets.com/en/topic-11663.html
    Objective:          Expand a range using FOR
    WITH t AS
    (SELECT '2:4' pt
    FROM DUAL
    UNION ALL
    SELECT '6:9' pt
    FROM DUAL)
    , base AS
    SELECT pt AS code_expression
    , KEY AS code
    , min_key
    , max_key
         , my_increment
    , m_1
    FROM t
    MODEL
    PARTITION BY (pt)
    DIMENSION BY ( CAST(0 AS NUMBER) AS KEY )
    MEASURES (
                        CAST(NULL AS CHAR) AS m_1,
                        TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key,
                        TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key,     
                        .1 AS my_increment     
    RULES
    -- UPSERT
              m_1[FOR KEY FROM min_key[0] TO max_key[0] INCREMENT 1] = 'Y'
    ORDER BY pt, KEY, m_1
    SELECT code_expression, code
    FROM base
    WHERE m_1 = 'Y'
    Explanation:
    Line numbers are based on the assupmtion that "WITH t AS" starts at line 5.
    If you need detailed information regarding the MODEL clause please refer to
    the Refrence site stated above or read some documentation.
    Partition-
    Line 21:     PARTITION BY (pt)
                   This will make sure that each "KEY" will start at 0 for each value of pt.
    Dimension-
    Line 22:     DIMENSION BY ( 0 AS KEY )     
                   This is necessary for the refrences max_key[0], and min_key[0] to work.
    Measures-
    Line 24:      CAST(NULL AS CHAR) AS m_1
                   A space holder for results.
    Line 25:     TO_NUMBER(SUBSTR(pt, 1, INSTR(pt, ':') - 1)) AS min_key
                   The result is '1' for '1:5'.
    Line 26:     TO_NUMBER(SUBSTR(pt, INSTR(pt, ':') + 1)) AS max_key                                        
                   The result is '5' for '1:5'.
    Line 27:     .1 AS my_increment     
                   The INCREMENT I would like to use.
    Rules-
    Line 30:     UPSERT
                   This makes it possible for new rows to be created.
                   However seems like it is not necessary.
    Line 32:     m_1[FOR KEY FROM min_key[0] TO max_key[0] INCREMENT 1] = 'Y'
                   Where the KE value is between min_key[0] and max_key[0] set the value of m_1 to 'Y'
    */

    Of course, you can accomplish the same thing without MODEL using an Integer Series Generator like this.
    create table t ( min_val number, max_val number, increment_size number );
    insert into t values ( 2, 3, 0.1 );
    insert into t values ( 1.02, 1.08, 0.02 );
    commit;
    create table integer_table as
      select rownum - 1 as n from all_objects where rownum <= 100 ;
    select
      min_val ,
      increment_size ,
      min_val + (increment_size * n) as val
    from t, integer_table
    where
      n between 0 and ((max_val - min_val)/increment_size)
    order by 3
       MIN_VAL INCREMENT_SIZE        VAL
          1.02            .02       1.02
          1.02            .02       1.04
          1.02            .02       1.06
          1.02            .02       1.08
             2             .1          2
             2             .1        2.1
             2             .1        2.2
             2             .1        2.3
             2             .1        2.4
             2             .1        2.5
             2             .1        2.6
             2             .1        2.7
             2             .1        2.8
             2             .1        2.9
             2             .1          3
    15 rows selected.--
    Joe Fuda
    http://www.sqlsnippets.com/

  • Cell assignments in Model clause

    Hi,
    I have a table TEST_DATA with YEAR,FIELD,VALUE as columns.
    The VALUE1 , VALUE2, VALUE 3 columns are determined based on the field values. If the data is as follows
    YEAR FIELD VALUE
    2010 1 11111
    2010 2 22222
    2010 3 33333
    Can I get the output as follows using model clause.
    YEAR VALUE1 VALUE2 VALUE3
    2010 11111 222222 333333
    2009 23243 533635 343434
    2008 34343 364653 343434
    2007 34345 789879 343434
    I don't want to use pivot as I have to perform some computations on the above value columns. So I tried the following query using model clause
    and value1,value2,value3 are coming in 3 different rows.
    How do I write cell assignments to get the value 1,value 2,value 3 in the same row?
    SELECT YEAR, VALUE 1,VALUE 2, VALUE 3
    FROM TEST_FIN_DATA
    MODEL
    RETURN UPDATED ROWS
    MAIN simple
    PARTITION BY (YEAR)
    DIMENSION BY (FIELD)
    MEASURES (VALUE VALUE1, VALUE VALUE2, VALUE VALUE3 )
    RULES
    (value1['1'] = value1['1'] ,
    value[('2'] = value['2'],
    value['3'] = value['3']);

    with data as (
      select 2010 y, 1 f, 11111 v from dual union all
      select 2010, 2, 222222 from dual union all
      select 2010, 3, 333333 from dual union all
      select 2009, 1, 111111 from dual union all
      select 2009, 2, 222222 from dual union all
      select 2009, 3, 333333 from dual
    select y, v1, v2, v3 from
    data
    model
    return updated rows
    partition by (y)
    dimension by (f)
    measures (v, 0 v1, 0 v2, 0 v3)
    rules(
    v1[0]=v[1]
    ,v2[0]=v[2]
    ,v3[0]=v[3]
    order by y desc
    Y;V1;V2;V3
    2010;11111;222222;333333
    2009;111111;222222;333333compare to the query without return updated rows.
    Trick is v?[0] creates a new (PIVOT-)row for every partition.
    regards
    Edited by: chris227 on 27.06.2012 06:15

  • Learning MODEL clause

    Hi Gurus,
    I am trying to learn MODEL clause.
    How can we achieve the below result in model clause
    create table t(c1 number);
    insert into t values(11);
    insert into t values(30);
    insert into t values(45);
    select *
    from t;
    C1
    11
    30
    45 Need to take MIN(C1) as from and MAX(C1) as to values
    Then split this range with a gap of 10. Output should be
    FROM_C1          TO_C1
    11          20
    21          30
    31          40
    41          45How can we do this using MODEL.
    I am not getting how to bring the FROM and TO value to the MODEL calsuse, as they are neither DIMENSION nor MEASURE
    Thanks.

    Hi Peter,
    I'm quite happy it looks similar to what I've done.
    This was my first use of MODEL though:
    WITH t AS
       SELECT 11 c1 FROM DUAL UNION ALL
       SELECT 30 c1 FROM DUAL UNION ALL
       SELECT 45 c1 FROM DUAL
    t_val AS
       SELECT MIN(c1) min_c1
            , MAX(c1) max_c1
        FROM t
    SELECT f AS from_c1, t AS to_c1
      FROM t_val model
         DIMENSION BY ( 1 AS x )
         MEASURES ( min_c1 AS mn
                  , max_c1 AS mx
                  , 1      AS f
                  , 1      AS t
         RULES UPSERT
         ITERATE (999)UNTIL(t[ITERATION_NUMBER+1]>=mx[1])
            f[ITERATION_NUMBER + 1]=f[ITERATION_NUMBER]+ 10,
            f[1] = mn[1],
            t[ITERATION_NUMBER+1] = LEAST(f[ITERATION_NUMBER+1]+9, mx[1])
    ORDER BY f, t;
    Output:
       FROM_C1      TO_C1
            11         20
            21         30
            31         40
            41         45And after seen your example I have understood that it could be simplified by directly using the MIN and MAX value in this way:
    WITH t AS
       SELECT 11 c1 FROM DUAL UNION ALL
       SELECT 30 c1 FROM DUAL UNION ALL
       SELECT 45 c1 FROM DUAL
    SELECT f AS from_c1, t AS to_c1
      FROM t model
         DIMENSION BY ( 1 AS x )
         MEASURES ( MIN(c1) AS mn
                  , MAX(c1) AS mx
                  , 1      AS f
                  , 1      AS t
         RULES UPSERT
         ITERATE (999)UNTIL(t[ITERATION_NUMBER + 1]>= mx[1])
            f[ITERATION_NUMBER + 1] = mn[1] + 10 * ITERATION_NUMBER,
            t[ITERATION_NUMBER + 1] = LEAST(f[ITERATION_NUMBER + 1] + 9, mx[1])
    ORDER BY f, t;Regards.
    Al
    Edited by: Alberto Faenza on Oct 29, 2012 5:48 PM
    Added simplified example after seeing Peter's code

  • Compute totals and subtotals with model clause

    Please help,
    I am using the model clause for the first time and need something like this, but no rule definition for every deptno:
    SQL> select deptno, empno, ename, sal
      2    from emp
      3  model
      4    dimension by (deptno, empno, ename)
      5    measures(sal)
      6    rules (
      7       sal[10, null, 'ZZ-Sum'] = sum(sal)[10, any, any]
      8      ,sal[20, null, 'ZZ-Sum'] = sum(sal)[20, any, any]
      9      ,sal[30, null, 'ZZ-Sum'] = sum(sal)[30, any, any]
    10      ,sal[null, null, 'ZZ-All'] = sum(sal)[any, any, 'ZZ-Sum']
    11       )
    12   order by deptno, empno, ename
    13  /
        DEPTNO      EMPNO ENAME             SAL
            10       7782 CLARK            2450
            10       7839 KING             5000
            10       7934 MILLER           1300
            10            ZZ-Sum           8750
            20       7369 SMITH             800
            20       7566 JONES            2975
            20       7788 SCOTT            3000
            20       7876 ADAMS            1100
            20       7902 FORD             3000
            20            ZZ-Sum          10875
            30       7499 ALLEN            1600
            30       7521 WARD             1250
            30       7654 MARTIN           1250
            30       7698 BLAKE            2850
            30       7844 TURNER           1500
            30       7900 JAMES             950
            30            ZZ-Sum           9400
                          ZZ-All          29025
    18 rows selected.Regards
    eri

    Many thanks to you! Your hint shows me, that in this case the model clause is not the right way to go.
    The statement below fits exactly my requirements:
    SQL> select
      2     g.deptno,
      3     e.empno,
      4     decode(g.grouping_empno,
      5        1, decode(g.deptno, null, 'All-Total:', 'Dept-Total:'),
      6           e.ename) emp_name,
      7     e.job, g.sum_sal salary
      8    from (select deptno, empno, grouping(empno) grouping_empno, sum(sal) sum_sal
      9            from emp
    10           group by rollup(deptno, empno)
    11           order by deptno, grouping(empno), empno) g, emp e
    12   where g.empno = e.empno (+)
    13  /
        DEPTNO      EMPNO EMP_NAME        JOB           SALARY
            10       7782 CLARK           MANAGER         2450
            10       7839 KING            PRESIDENT       5000
            10       7934 MILLER          CLERK           1300
            10            Dept-Total:                     8750
            20       7369 SMITH           CLERK            800
            20       7566 JONES           MANAGER         2975
            20       7788 SCOTT           ANALYST         3000
            20       7876 ADAMS           CLERK           1100
            20       7902 FORD            ANALYST         3000
            20            Dept-Total:                    10875
            30       7499 ALLEN           SALESMAN        1600
            30       7521 WARD            SALESMAN        1250
            30       7654 MARTIN          SALESMAN        1250
            30       7698 BLAKE           MANAGER         2850
            30       7844 TURNER          SALESMAN        1500
            30       7900 JAMES           CLERK            950
            30            Dept-Total:                     9400
                          All-Total:                     29025
    18 rows selected.Regards
    eri

  • Bin fitting with a counter using both analytics and model clause.

    11.2.0.3
    This falls under 'just want to figure out how to do it'. Its not critical for work. I want to try to see if its possible to do this with both analytic function and with a model clause. Just to see if its possible. It has been stumping me.
    I got the idea to look at this from this article about bin fitting. I have been playing with the model clause and I think you would do something with the 'increment' clause, but I dont see a way to reset it to 1 at a certain point.
    http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22asktom-1518271.html
    The case I want to look at is, bin fitting based on a counter and a partition by. In theory this should be simpler than the example in the link.
    [code]
    create table myrooms (
    room_number number,
    person_id        number);
    create unique index myrooms_ind on myrooms(room_number,person_id);
    [/code]
    Person_id is not unique. So row_number is more appropriate than rank or dense_rank.
    Problem: Partition by room_number, assign up to 50 people to a specific group with in the same room. This seems like it could be handled with a row_number() and a window clause, but that is not supported.
    I need to basically translate the old procedural counter into sql:
    pseudo-code that does not compile that would have a reason to use this logic.
    [code]
    declare
      cursor curGetRoom
         select room_number,person_id
            from my rooms
          order by room_number;
    counter number := 1;
    vCurrentRoom myroom.room_number%type;
    begin
        for i in curGetRoom loop
            if vCurrentRoom is null then
               vCurrentRoom := i.room_number;
            elsif vCurrentRoom = i.room_number then
                  if counter < 51 then counter :=counter+1;
                  else counter := 1;
            else
                 vCurrentRoom := i.room_number;
                counter :=1;
            end if;
    end;
    [/code]
    simple partition query., but I dont see a way to limit this to 50 and then start over. Window functions are not supported with row_number()
    [code]
    select room_number,person_id,row_number() over (partition by room_number order by person_id) rn
    from myrooms
    [/code]

    11.2.0.3
    This falls under 'just want to figure out how to do it'. Its not critical for work. I want to try to see if its possible to do this with both analytic function and with a model clause. Just to see if its possible. It has been stumping me.
    I got the idea to look at this from this article about bin fitting. I have been playing with the model clause and I think you would do something with the 'increment' clause, but I dont see a way to reset it to 1 at a certain point.
    http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22asktom-1518271.html
    The case I want to look at is, bin fitting based on a counter and a partition by. In theory this should be simpler than the example in the link.
    [code]
    create table myrooms (
    room_number number,
    person_id        number);
    create unique index myrooms_ind on myrooms(room_number,person_id);
    [/code]
    Person_id is not unique. So row_number is more appropriate than rank or dense_rank.
    Problem: Partition by room_number, assign up to 50 people to a specific group with in the same room. This seems like it could be handled with a row_number() and a window clause, but that is not supported.
    I need to basically translate the old procedural counter into sql:
    pseudo-code that does not compile that would have a reason to use this logic.
    [code]
    declare
      cursor curGetRoom
         select room_number,person_id
            from my rooms
          order by room_number;
    counter number := 1;
    vCurrentRoom myroom.room_number%type;
    begin
        for i in curGetRoom loop
            if vCurrentRoom is null then
               vCurrentRoom := i.room_number;
            elsif vCurrentRoom = i.room_number then
                  if counter < 51 then counter :=counter+1;
                  else counter := 1;
            else
                 vCurrentRoom := i.room_number;
                counter :=1;
            end if;
    end;
    [/code]
    simple partition query., but I dont see a way to limit this to 50 and then start over. Window functions are not supported with row_number()
    [code]
    select room_number,person_id,row_number() over (partition by room_number order by person_id) rn
    from myrooms
    [/code]

  • Using the Case clause with Model clause

    Hello PL SQL gurus
    I've used some scripts I've found on these forums to create a mortgage amortization statement. What I am trying to accomplish is getting the script to run a calculation or use a value within a table based upon the value in that table.
    Here are the two tables:
    CREATE TABLE mortgage_facts (customer VARCHAR2(20), fact VARCHAR2(20),
    amount NUMBER(10,3));
    INSERT INTO mortgage_facts VALUES ('Smith', 'Loan', 131828.81);
    INSERT INTO mortgage_facts VALUES ('Smith', 'Annual_Interest', 3.348);
    INSERT INTO mortgage_facts VALUES ('Smith', 'Payments', 72);
    INSERT INTO mortgage_facts VALUES ('Smith', 'PaymentAmt', 0);
    CREATE TABLE mortgage (customer VARCHAR2(20), pmt_num NUMBER(4), principalp NUMBER(10,3), interestp NUMBER(10,3), mort_balance NUMBER(10,3));
    INSERT INTO mortgage VALUES ('Smith',0, 0, 0, 131828.81);
    If the value within the table mortgage_facts is zero, I want the script to run a calculation to be used in a MODEL clause. If it is not zero, I would like to use that value instead of the calculation. Below is the script that I am getting an error on (I have bolded the portion in question):
    SELECT c, p, to_char(round(m,2),'fm$9999999.00') principal_balance,
    to_char(round(pp,2),'fm$9999999.00') towards_principal,
    to_char(round(ip,2),'fm$9999999.00') towards_interest,
    to_char(round(mp,2),'fm$9999999.00') monthly_payment
    FROM MORTGAGE
    MODEL --See 1
    IGNORE NAV
    REFERENCE R ON
    *(SELECT customer, fact, amt --See 2*
    FROM mortgage_facts
    *MODEL DIMENSION BY (customer, fact) MEASURES (amount amt)          --See 3*
    RULES SEQUENTIAL ORDER
    CASE WHEN mortgage_facts.fact = 'PaymentAmt' AND mortage_facts.amt = 0 THEN
    *amt[ANY, 'PaymentAmt'] = mortgage_facts.amt*
    ELSE
    *amt[any, 'PaymentAmt']= (amt[CV(),'Loan']**
    *Power(1+ (amt[CV(),'Annual_Interest']/100/12),*
    *amt[CV(),'Payments']) **
    *(amt[CV(),'Annual_Interest']/100/12)) /*
    *(Power(1+(amt[CV(),'Annual_Interest']/100/12),*
    *amt[CV(),'Payments']) - 1)*
    END
    DIMENSION BY (customer cust, fact) measures (amt)
    MAIN amortization
    PARTITION BY (customer c)
    DIMENSION BY (0 p)
    MEASURES (principalp pp, interestp ip, mort_balance m, customer mc, 0 mp )
    RULES SEQUENTIAL ORDER
    ITERATE(1000) UNTIL (ITERATION_NUMBER+1 =
    r.amt[mc[0],'Payments'])
    (ip[ITERATION_NUMBER+1] = m[CV()-1] *
    r.amt[mc[0], 'Annual_Interest']/1200,
    mp[ITERATION_NUMBER+1] = r.amt[mc[0], 'PaymentAmt'],
    pp[ITERATION_NUMBER+1] = r.amt[mc[0], 'PaymentAmt'] - ip[CV()],
    m[ITERATION_NUMBER+1] = m[CV()-1] - pp[CV()]
    ORDER BY c, p
    Any help is much appreciated. Thank you!!

    Ok, here we go, one way with iterative model:
    select *
    from mortgage_facts
    model
    partition by (Customer)
    dimension by (1 p)
    measures(loan, payments, INTEREST, PAYMENTAMT, INTERESTPMT, PRINCIPALPMT, balance)
    rules iterate(1e9) until (iteration_number+2 >= payments[1])
    (loan[iteration_number+2]=loan[1]
    ,payments[iteration_number+2]=cv(p)-1
    ,interest[iteration_number+2]=interest[1]
    ,paymentamt[iteration_number+2]=ROUND(
      (LOAN[1] * (INTEREST[1]/12/100)*Power((1+INTEREST[1]/12/100), PAYMENTS[1])/(Power((1+INTEREST[1]/12/100),PAYMENTS[1])-1)), 2)
    ,INTERESTPMT[iteration_number+2]=round(balance[cv(p)-1]*interest[1]/1200, 2)
    ,PRINCIPALPMT[iteration_number+2]=paymentamt[cv()]-INTERESTPMT[cv()]
    ,balance[iteration_number+2]=balance[cv()-1]-PRINCIPALPMT[cv()]
    CUSTOMER     P     LOAN     PAYMENTS     INTEREST     PAYMENTAMT     INTERESTPMT     PRINCIPALPMT     BALANCE
    Smith     1     131828.81     72     3.348     0     0     0     131828.81
    Smith     2     131828.81     1     3.348     2023.55     367.8     1655.75     130173.06
    Smith     3     131828.81     2     3.348     2023.55     363.18     1660.37     128512.69
    Smith     4     131828.81     3     3.348     2023.55     358.55     1665     126847.69
    Smith     5     131828.81     4     3.348     2023.55     353.91     1669.64     125178.05
    Smith     6     131828.81     5     3.348     2023.55     349.25     1674.3     123503.75
    Smith     7     131828.81     6     3.348     2023.55     344.58     1678.97     121824.78
    Smith     8     131828.81     7     3.348     2023.55     339.89     1683.66     120141.12
    Smith     9     131828.81     8     3.348     2023.55     335.19     1688.36     118452.76
    Smith     10     131828.81     9     3.348     2023.55     330.48     1693.07     116759.69
    Smith     11     131828.81     10     3.348     2023.55     325.76     1697.79     115061.9
    Smith     12     131828.81     11     3.348     2023.55     321.02     1702.53     113359.37
    Smith     13     131828.81     12     3.348     2023.55     316.27     1707.28     111652.09
    Smith     14     131828.81     13     3.348     2023.55     311.51     1712.04     109940.05
    ....

  • MODEL clause to process a comma separated string

    Hi,
    I'm trying to parse a comma separated string using SQL so that it will return the parsed values as rows;
    eg. 'ABC,DEF GHI,JKL' would return 3 rows;
    'ABC'
    'DEF GHI'
    'JKL'
    I'm thinking that I could possibily use the MODEL clause combined with REGULAR expressions to solve this as I've already got a bit of SQL which does the opposite ie. turning the rows into 1 comma separated string;
    select id, substr( concat_string, 2 ) as string
    from (select 1 id, 'ABC' string from dual union all select 1, 'DEF GHI' from dual union all select 1, 'JKL' from dual)
    model
    return updated rows
    partition by ( id )
    dimension by ( row_number() over (partition by id order by string) as position )
    measures ( cast(string as varchar2(4000) ) as concat_string )
    rules
    upsert
    iterate( 1000 )
    until ( presentv(concat_string[iteration_number+2],1,0) = 0 )
    ( concat_string[0] = concat_string[0] || ',' || concat_string[iteration_number+1] )
    order by id;
    Can anyone give me some pointers how to parse the comma separated string using regexp and create as many rows as needed using the MODEL clause?

    Yes, you could do it without using ITERATE, but FOR ... INCREMENT is pretty much same loop. Couple of improvements:
    a) there is no need for CHAINE measure
    b) there is no need for CASE in RULES clause
    c) NVL can be applies on measures level
    with t as (select 1 id, 'ABC,DEF GHI,JKL,DEF GHI,JKL,DEF GHI,JKL,DEF,GHI,JKL' string from dual
       union all
        select 2,'MNO' string from dual
        union all
       select 3,null string from dual
    SELECT  id,
             string
      FROM   T
       MODEL
        RETURN UPDATED ROWS
        partition by (id)
        DIMENSION BY (0 POSITION)
        MEASURES(
                 string,
                 NVL(LENGTH(REGEXP_REPLACE(string,'[^,]+','')),0)+1 NB_MOT
        RULES
         string[FOR POSITION FROM  1 TO NB_MOT[0] INCREMENT 1] = REGEXP_SUBSTR(string[0],'[^,]+',1,CV(POSITION))
    SQL> with t as (select 1 id, 'ABC,DEF GHI,JKL,DEF GHI,JKL,DEF GHI,JKL,DEF,GHI,JKL' string from dual
      2     union all
      3      select 2,'MNO' string from dual
      4      union all
      5     select 3,null string from dual
      6      )
      7   SELECT  id,
      8           string
      9    FROM   T
    10     MODEL
    11      RETURN UPDATED ROWS
    12      partition by (id)
    13      DIMENSION BY (0 POSITION)
    14      MEASURES(
    15               string,
    16               NVL(LENGTH(REGEXP_REPLACE(string,'[^,]+','')),0)+1 NB_MOT
    17              )
    18      RULES
    19      (
    20       string[FOR POSITION FROM  1 TO NB_MOT[0] INCREMENT 1] = REGEXP_SUBSTR(string[0],'[^,]+',1,CV(POSITION))
    21      )
    22  /
            ID STRING
             1 ABC
             1 DEF GHI
             1 JKL
             1 DEF GHI
             1 JKL
             1 DEF GHI
             1 JKL
             1 DEF
             1 GHI
             1 JKL
             2 MNO
            ID STRING
             3
    12 rows selected.
    SQL> SY.

  • MODEL clause using CONNECY BY PRIOR

    Hello.
    I have the following table, CONTEXT_MAPPING:
    Name Null? Type
    ID NOT NULL NUMBER(38)
    CONTEXT_ITEM NOT NULL VARCHAR2(30)
    ID_1 NUMBER(38)
    ID_2 NUMBER(38)
    ID_3 NUMBER(38)
    ID_4 NUMBER(38)
    ID_5 NUMBER(38)
    It's a self referencing table, i.e. ID_1 will refer to an ID from another row in CONTEXT_MAPPING, and the same for ID_2/3/4/5.
    Easily illustrated through the following hierarchical data:
    ID CONTEXT_ITEM ID1 ID2 ID3 ID4 ID5
    1 P_DMA_NDA_ID
    2 P_DS_NDA_ID 1
    3 P_AST_NDA_ID 2 1
    4 P_AGI_ID 3
    5 P_ASG_NDA_ID 3
    6 P_NTS_FACTS 5 5
    7 P_IDE_VALUE 2 1
    8 P_EIT_VALUE 2 1
    9 P_TRI_TABLE 4 6 7 8
    10 P_TRI 9
    11 P_PRICE1 6 10 6
    12 P_PRICE2 6 10 6
    What I want to do, is for any context item, to identify ALL of its dependencies throughout the tree.
    For example:
    P_PRICE2 has a link to P_NTS_FACTS (ID1 & ID3 = 6) and P_TRI (ID2 = 10)
    P_NTS_FACTS has a link to P_ASG_NDA_ID (ID1 & ID2 = 5), which in turn links to P_AST_NDA_ID (ID1 = 3)...
    P_TRI has a link to P_TRI_TABLE (ID1 = 9), which in turn links to multiple context items (ID1 = 4, ID2 = 6 etc.) ....
    ....and so on, until we get to the "root" record, P_DMA_NDA_ID.
    So, to see the complete dependency tree for P_PRICE2, I would expect to see a hierarchical result-set like this:
    ID CONTEXT_ITEM ID1 ID2 ID3 ID4 ID5
    12 P_PRICE2 6 10 6
    10 P_TRI 9
    9 P_TRI_TABLE 4 6 7 8
    4 P_AGI_ID 3
    6 P_NTS_FACTS 5 5
    5 P_ASG_NDA_ID 3
    3 P_AST_NDA_ID 2 1
    7 P_IDE_VALUE 2 1
    8 P_EIT_VALUE 2 1
    2 P_DS_NDA_ID 1
    1 P_DMA_NDA_ID
    Ideally I want to do this in a single SQL statement - I've tried using CONNECT BY PRIOR in conjunction with LEVEL to do this, but it only performs a hierarchical join for a single child-parent relationship, and I need this to work for up to five children.
    Was starting to wonder if I could use the MODEL clause in conjunction with CONNECT BY PRIOR to achieve this - does anyone have any idea whether this type of recursion is possible?
    Thanks,
    Ray

    it only performs a hierarchical join for a single child-parent relationshipBeg to differ.
    Oracle Database 10g Release 10.2.0.2.0 - Production
    SQL> CREATE TABLE context_mapping (
      2     id NUMBER(38),
      3     context_item VARCHAR2(30),
      4     id_1 NUMBER(38),
      5     id_2 NUMBER(38),
      6     id_3 NUMBER(38),
      7     id_4 NUMBER(38),
      8     id_5 NUMBER(38));
    Table created.
    SQL> INSERT INTO context_mapping VALUES (1, 'P_DMA_NDA_ID', NULL, NULL, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (2, 'P_DS_NDA_ID', 1, NULL, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (3, 'P_AST_NDA_ID', 2, 1, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (4, 'P_AGI_ID', 3, NULL, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (5, 'P_ASG_NDA_ID', 3, NULL, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (6, 'P_NTS_FACTS', 5, 5, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (7, 'P_IDE_VALUE', 2, 1, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (8, 'P_EIT_VALUE', 2, 1, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (9, 'P_TRI_TABLE', 4, 6, 7, 8, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (10, 'P_TRI', 9, NULL, NULL, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (11, 'P_PRICE1', 6, 10, 6, NULL, NULL);
    1 row created.
    SQL> INSERT INTO context_mapping VALUES (12, 'P_PRICE2', 6, 10, 6, NULL, NULL);
    1 row created.
    SQL> SELECT DISTINCT id, context_item, id_1, id_2, id_3, id_4, id_5
      2  FROM   context_mapping
      3  START WITH id = 12
      4  CONNECT BY id IN (PRIOR id_1, PRIOR id_2, PRIOR id_3, PRIOR id_4, PRIOR id_5)
      5  ORDER BY id DESC;
            ID CONTEXT_ITEM                         ID_1       ID_2       ID_3       ID_4       ID_5
            12 P_PRICE2                                6         10          6
            10 P_TRI                                   9
             9 P_TRI_TABLE                             4          6          7          8
             8 P_EIT_VALUE                             2          1
             7 P_IDE_VALUE                             2          1
             6 P_NTS_FACTS                             5          5
             5 P_ASG_NDA_ID                            3
             4 P_AGI_ID                                3
             3 P_AST_NDA_ID                            2          1
             2 P_DS_NDA_ID                             1
             1 P_DMA_NDA_ID
    11 rows selected.
    SQL>

  • Unable to display data no entry in the table without using Model clause

    Hi,
    I've an urgent requirement described below :
    The previously posted Question has been answerted using Model Clause:
    Is there any way out to solve it without using Model clause:
    I've a table named as "sale" consisting of three columns : empno, sale_amt and sale_date.
    (Please ref. The table script with data as given below)
    Now if I execute the query :
    "select trunc(sale_date) sale_date, sum(sale_amt) total_sale from sale group by trunc(sale_date) order by 1"
    then it displays the data for the dates of which there is an entry in that table. But it does not display data for the
    date of which there is no entry in that table.
    If you run the Table script with data in your schema, then u'll see that there is no entry for 28th. Nov. 2009 in
    sale table. Now the above query displays data for rest of the dates as its are in sale table except for 28th. Nov. 2009.
    But I need its presence in the query output with a value of "sale_date" as "28th. Nov. 2009" and that of "total_sale" as
    "0".
    Is there any means to get the result as I require?
    Please help ASAP.
    Thanks in advance.
    Create table script with data:
    CREATE TABLE SALE
    EMPNO NUMBER,
    SALE_AMT NUMBER,
    SALE_DATE DATE
    SET DEFINE OFF;
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (100, 1000, TO_DATE('12/01/2009 10:20:10', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (100, 1000, TO_DATE('11/30/2009 10:21:04', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (100, 1000, TO_DATE('11/29/2009 10:21:05', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (100, 1000, TO_DATE('11/26/2009 10:21:06', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (100, 1000, TO_DATE('11/25/2009 10:21:07', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (200, 5000, TO_DATE('11/27/2009 10:23:06', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (200, 4000, TO_DATE('11/29/2009 10:23:08', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (200, 3000, TO_DATE('11/24/2009 10:23:09', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (200, 2000, TO_DATE('11/30/2009 10:23:10', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (300, 7000, TO_DATE('11/24/2009 10:24:19', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (300, 5000, TO_DATE('11/25/2009 10:24:20', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (300, 3000, TO_DATE('11/27/2009 10:24:21', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (300, 2000, TO_DATE('11/29/2009 10:24:22', 'MM/DD/YYYY HH24:MI:SS'));
    Insert into SALE
    (EMPNO, SALE_AMT, SALE_DATE)
    Values
    (300, 1000, TO_DATE('11/30/2009 10:24:22', 'MM/DD/YYYY HH24:MI:SS'));
    COMMIT;
    Any help will be needful for me
    Regards,

    select sale_date,sum(sale_amt) total_sale
    from
    select empno,0 sale_amt,(sale_date + ao.rn) sale_date
    from
    select empno,sale_amt,sale_date ,(t.nxt_dt - t.sale_date) diff
    from
    select empno
    ,sale_amt,trunc(sale_date) sale_date
    ,trunc(nvl(lead(sale_date) over (partition by 1 order by sale_date),sale_date)) nxt_dt
    from sale
    ) t
    where (t.nxt_dt - t.sale_date) >1
    ) rec,(select rownum rn from user_objects where rownum<=200) ao
    where ao.rn <=(rec.diff-1)
    union all
    select empno,sale_amt,trunc(sale_date) sale_date
    from sale
    group by sale_date
    order by 1;
    ~~~~Guess this will serve the purpose...
    Cheers Arpan

  • Pivoting using Model Clause Vs pivoting using Aggregate Fun(Case) statement

    Hi,
    I just wanted to know which option is better for pivoting the data if the data is like:
    Grp1 Grp2 Day_week Sales
    1 1 Sun 200
    1 1 Mon 100
    1 2 Sun 1000
    and so on...
    The output should be:
    Grp1 Grp2 Sun Mon ......
    1 1 200 100.....
    1 2 1000 NULL....
    I have tested the same using sum(decode...) method and also model clause:
    select grp1, grp2, sum(decode(day_week,'SUN',sales)) SUNDAY , sum(decode(day_week,'MON',sales)) MONDAY from pivot
    group by grp1, grp2
    order by grp1, grp2
    select grp1, grp2, sun , mon, tue, wed, thr, fri, sat
    from pivot
    model -- UNIQUE SINGLE REFERENCE
    return updated rows
    partition by (grp1, grp2)
    dimension by ( day_week)
    measures( result, 0 mon, 0 tue, 0 wed, 0 thr,0 fri, 0 sat, 0 sun)
    RULES upsert
    mon[0]= sales['MON'],
    tue[0]= sales['TUE'],
    wed[0]= sales['WED'],
    thr[0]= sales['THR'],
    fri[0]= sales['FRI'],
    sat[0]= sales['SAT'],
    sun[0]= sales['SUN']
    ) order by grp1, grp2
    There are 4K records in the table. The first query is taking app (.125 seconds) and the second query (.230 seconds).
    Pls tell how the model clause can give better performance and I want to use it for pivoting in all my APIs.
    Regards
    Rajiv

    > I read somewhere while searching on net.
    And now you can't find it anymore? I wouldn't believe anything you read somewhere while searching on net, unless it has some kind of proof attached.
    > You pls tell is it so or it depends upon volume of data.
    Also i tested on some data and reults were better in
    case of using normal startegy rather than model.(case
    provided above).
    So you have tested it yourself already. The model clause is great in a few cases (string aggregation, calculating values based on calculated values), but this doesn't seem to be one of them. On 11g you might want to consider the PIVOT operator.
    Regards,
    Rob.

  • Using MODEL clause and COUNT for not numeric data columns....

    Hi ,
    Is it possible somehow to use the COUNT function to transform a non-numeric data column to a numeric data value (a counter) and be used in a MODEL clause....????
    For example , i tried the following in the emp table of SCOTT dataschema with no desired result...
    SQL> select deptno , empno , hiredate from emp;
    DEPTNO EMPNO HIREDATE
        20  7369 18/12/1980
        30  7499 20/02/1981
        30  7521 22/02/1981
        20  7566 02/04/1981
        30  7654 28/09/1981
        30  7698 01/05/1981
        10  7782 09/06/1981
        20  7788 18/04/1987
        10  7839 17/11/1981
        30  7844 08/09/1981
        20  7876 21/05/1987
        30  7900 03/12/1981
        20  7902 03/12/1981
        10  7934 23/01/1982
    14 rows selected Now , i want to use the MODEL clause in order to 'predict' the number of employees who were going to be hired in the 1990 per deptno...
    So , i have constructed the following query which , as expected, does not return the desired results....
    SQL>   select deptno , month , year , count_
      2    from
      3    (
      4    select deptno , to_number(to_char(hiredate,'mm')) month ,
      5                to_number(to_char(hiredate , 'rrrr')) year , count(ename) count_
      6    from emp
      7    group by  deptno , to_number(to_char(hiredate,'mm'))  ,
      8                to_number(to_char(hiredate , 'rrrr'))
      9    )
    10    model
    11    partition by(deptno)
    12    dimension by (month , year)
    13    measures (count_ )
    14    (
    15     count_[1,1990]=count_[1,1982]+count_[11,1982]
    16    )
    17  /
        DEPTNO      MONTH       YEAR     COUNT_
            30          5       1981          1
            30         12       1981          1
            30          2       1981          2
            30          9       1981          2
            30          1       1990
            20          4       1987          1
            20          5       1987          1
            20          4       1981          1
            20         12       1981          1
            20         12       1980          1
            20          1       1990
            10          6       1981          1
            10         11       1981          1
            10          1       1982          1
            10          1       1990 As you see , the measures for the 1990 year is null...because the measure(the count(deptno)) is computed via the group by and not by the MODEL clause...
    How should i transform the above query... so as the "count_[1,1982]+count_[11,1982]" will return non-null results per deptno...????
    Thanks , a lot
    Simon

    Connected to Oracle Database 10g Express Edition Release 10.2.0.1.0
    Connected as hr
    SQL>
    SQL> SELECT department_id, MONTH, YEAR, count_
      2    FROM (SELECT e.department_id
      3                ,to_number(to_char(e.hire_date, 'mm')) MONTH
      4                ,to_number(to_char(e.hire_date, 'rrrr')) YEAR
      5                ,COUNT(e.first_name) count_
      6            FROM employees e
      7            WHERE e.department_id = 20
      8           GROUP BY e.department_id
      9                   ,to_number(to_char(e.hire_date, 'mm'))
    10                   ,to_number(to_char(e.hire_date, 'rrrr')));
    DEPARTMENT_ID      MONTH       YEAR     COUNT_
               20          8       1997          1
               20          2       1996          1
    SQL> --
    SQL> SELECT department_id, MONTH, YEAR, count_
      2    FROM (SELECT e.department_id
      3                ,to_number(to_char(e.hire_date, 'mm')) MONTH
      4                ,to_number(to_char(e.hire_date, 'rrrr')) YEAR
      5                ,COUNT(e.first_name) count_
      6            FROM employees e
      7            WHERE e.department_id = 20
      8           GROUP BY e.department_id
      9                   ,to_number(to_char(e.hire_date, 'mm'))
    10                   ,to_number(to_char(e.hire_date, 'rrrr')))
    11  model
    12  PARTITION BY(department_id)
    13  dimension BY(MONTH, YEAR)
    14  measures(count_)(
    15    count_ [1, 1990] = count_ [2, 1996] + count_ [8, 1997]
    16  );
    DEPARTMENT_ID      MONTH       YEAR     COUNT_
               20          8       1997          1
               20          2       1996          1
               20          1       1990          2
    SQL> ---
    SQL> SELECT department_id, MONTH, YEAR, count_
      2    FROM (SELECT e.department_id
      3                ,to_number(to_char(e.hire_date, 'mm')) MONTH
      4                ,to_number(to_char(e.hire_date, 'rrrr')) YEAR
      5                ,COUNT(e.first_name) count_
      6            FROM employees e
      7           GROUP BY e.department_id
      8                   ,to_number(to_char(e.hire_date, 'mm'))
      9                   ,to_number(to_char(e.hire_date, 'rrrr')))
    10  model ignore nav
    11  PARTITION BY(department_id)
    12  dimension BY(MONTH, YEAR)
    13  measures(count_)(
    14    count_ [1, 1990] = count_ [2, 1996] + count_ [8, 1997]
    15  );
    DEPARTMENT_ID      MONTH       YEAR     COUNT_
              100          8       1994          2
               30         12       1997          1
              100          3       1998          1
               30          7       1997          1
                           5       1999          1
               30         12       1994          1
               30         11       1998          1
               30          5       1995          1
              100          9       1997          2
              100         12       1999          1
               30          8       1999          1
                           1       1990          0
               30          1       1990          0
              100          1       1990          0
               90          9       1989          1
               20          8       1997          1
               70          6       1994          1
    93 rows selected
    SQL>

  • Trying to understand the MODEL clause

    Hi All,
    I'm finally biting the bullet and learning how to use the model clause, but I'm having a bit of trouble.
    The following example data comes from a book "Advanced CQL Functions in Oracle 10g".
    with sales1 as (select 'blueberries' product
                          ,'pensacola' location
                          ,9000 amount
                          ,2001 year
                      from dual
                    union all
                    select 'cotton', 'pensacola',16000,2001 from dual
                    union all
                    select 'lumber','pensacola',3500,2001 from dual
                    union all
                    select 'cotton','mobile',24000,2001 from dual
                    union all
                    select 'lumber', 'mobile',2800,2001 from dual
                    union all
                    select 'plastic','mobile',32000,2001 from dual
                    union all
                    select 'blueberries','pensacola',9000,2002 from dual
                    union all
                    select 'cotton', 'pensacola',16000,2002 from dual
                    union all
                    select 'lumber','pensacola',3500,2002 from dual
                    union all
                    select 'cotton','mobile',24000,2002 from dual
                    union all
                    select 'lumber', 'mobile',2800,2002 from dual
                    union all
                    select 'plastic','mobile',32000,2002 from dual
                    union all
                    select 'blueberries','pensacola',9000,2003 from dual
                    union all
                    select 'cotton', 'pensacola',16000,2003 from dual
                    union all
                    select 'lumber','pensacola',3500,2003 from dual
                    union all
                    select 'cotton','mobile',24000,2003 from dual
                    union all
                    select 'lumber', 'mobile',2800,2003 from dual
                    union all
                    select 'plastic','mobile',32000,2003 from dual
    select location, product, year, s
    from sales1
    model
    --return updated rows
    partition by (product)
    dimension by (location,year)
    measures (amount s) ignore nav
    (s['pensacola',2003] = sum(s)['pensacola',cv() > cv()-1])I would have expected the measures clause to return the sum of all amounts for pensacola where the year > 2003 - 1 = 2002. which would make the total for [blueberries,2003] = 1800, but instead it comes out as 27000, apparently summing all values for blueberries for that partition.... equivalent to sum(s)['pensacola',ANY].
    how would I go about making s['pensacola',2003] = the sum of itself plus the previous row?
    I realise I can do
    s['pensacola',cv()]+s['pensacola',cv()-1]but I'm really trying to understand why what I have doesn't appear to work the way I expect.

    Because
    (s['pensacola',2003] = sum(s)['pensacola',cv() > cv()-1])
    means
    (s['pensacola',2003] = sum(s)['pensacola',cv(year) > cv(year)-1])
    means
    (s['pensacola',2003] = sum(s)['pensacola',2003 > 2003-1])
    means
    (s['pensacola',2003] = sum(s)['pensacola',2003 > 2002])
    means
    (s['pensacola',2003] = sum(s)['pensacola',year is any])
    s['pensacola',cv()]+s['pensacola',cv()-1]
    means
    sum(s)['pensacola',year between cv()-1 and cv()]

Maybe you are looking for