MainBlogContactRSS




Login    
Login
 
Recent Entries    
Next Projects
INITCAP this!
APEX 3.1 released ...
Exploiting the strange behavio ...
Where's my SQL?
Undocumented Packages for Back ...
Debugging an APEX application
Splitting strings
Where's the space gone?
The size of a (XE) database
1 2 3 4 5 6 
Search    
Search
 
Recent Articles    
Introduction to Regular Expres ...
Extracting SQL statements from ...
BBCode Parser
MODEL clause vs. old school SQ ...
IF NULL or how to match two va ...
Views    
Firefox1241
IExplorer1597
Linux108
Windows2888
Total Views49333
System    
BCHR 
CMS_TS (100MB) 
DB (XE) (5GB) 
PGA (256MB) 
Daily insights of a database application developer    
MODEL clause vs. old school SQL [2007.12.16] Bookmark (1.0.0.0)

Finishing my blog entry on SQL for Modeling, here are some examples where the results of such an example should be equivalent to a non-MODEL clause solution. These examples should give you, the reader, an idea how this new clause works by comparing it with another statement. My personal take on the MODEL clause is: Use it when you need iterations or even recursions inside an SQL statement or when you need to apply a "spreadsheet" logic to your result set.

row "generator"

-- "connect by" method

SELECT dummy c1
  FROM dual
 CONNECT BY LEVEL <= 10
;  

-- "model" method

SELECT c1
  FROM dual
 MODEL
   DIMENSION BY (0 dim)
   MEASURES     (dummy c1)
   RULES ITERATE(10) (c1[ITERATION_NUMBER] = 'X')
;

C
-
X
X
X
X
X
X
X
X
X
X


Remove "," from fields with quotation marks (from the OTN-ThreadRegular expression)

WITH t AS (SELECT 'John,Doe,"$85,256",Programmer,"$42,857"' col1
             FROM dual
            UNION
           SELECT 'Mary,Jane,"$26,586",BA,"$42,857"'
             FROM dual
            UNION
           SELECT 'Test,,Test,",1", BA,",8"'
             FROM dual
          )
SELECT t.col1
     , REGEXP_REPLACE(t.col1, '("[^,]+),*([^,"]+),*([^,"]+),*([^,"]+),*', '1234') col3
  FROM t
;

WITH clause from previous SELECT
SELECT c1
     , c3
  FROM t
 MODEL
   PARTITION BY (ROWNUM rn)
   DIMENSION BY (0 dim)
   MEASURES(col1 c1, col1 c2, col1 c3)
   RULES ITERATE(10) UNTIL (c3[0]= PREVIOUS(c3[0]))
                (c2[0] = REGEXP_SUBSTR(c1[0], '("[^"]*"|[^,]*)(,|$)', 1, ITERATION_NUMBER + 1)
                ,c3[0] = DECODE(ITERATION_NUMBER, 0, '', c3[0]) || REPLACE(SUBSTR(c2[0], 1, LENGTH(c2[0]) - 1), ',', '') || SUBSTR(c2[0], -1)
                )
;

C1                                      C3
--------------------------------------- ---------------------------------------
John,Doe,"$85,256",Programmer,"$42,857" John,Doe,"$85256",Programmer,"$42857"
Mary,Jane,"$26,586",BA,"$42,857"        Mary,Jane,"$26586",BA,"$42857"
Test,,Test,",1", BA,",8"                Test,,Test,"1", BA,"8"


Split strings from the thread OTN thread a query.

WITH t AS (SELECT '10,12,20,30,30,3,12,12,56' col1
             FROM dual
          )
SELECT SUBSTR(col1
             ,DECODE(level, 1, 1, INSTR(col1,',',1,level-1)+1)
             ,DECODE(INSTR(col1,',',1,level), 0, LENGTH(col1), instr(col1,',',1,level)
             -DECODE(level, 1, 0, INSTR(col1,',',1,level-1))-1)
             ) col_new
  FROM t
  CONNECT BY level < LENGTH(REPLACE(TRANSLATE(col1,'01234567890','00000000000'),'0')) + 2
; 

WITH clause from previous SELECT
SELECT col_new
  FROM t
 MODEL
   PARTITION BY (ROWNUM rn)
   DIMENSION BY (0 dim)
   MEASURES(col1, col1 col_new)
   RULES ITERATE(99) UNTIL (ITERATION_NUMBER = LENGTH(REGEXP_REPLACE(col1[0], '[^,]')))
                (col_new[ITERATION_NUMBER] = REPLACE(REGEXP_SUBSTR(col1[0], '(^|,)[^,]*', 1, ITERATION_NUMBER+1), ','))
;

COL_NEW
-------------------------
10
12
20
30
30
3
12
12
56


Find soccer clubs with consecutive championships from the OTN-Thread sql question.

WITH champ AS (SELECT 'Chelsea' team_name, 1960 year 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1961 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1962 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1963 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1964
                 FROM dual
                UNION ALL 
               SELECT 'Manchester United', 1965
                 FROM dual 
                UNION ALL 
               SELECT 'Chelsea', 1966 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1967 
                 FROM dual
                UNION ALL 
               SELECT 'Chelsea', 1968 
                 FROM dual 
                UNION ALL 
               SELECT 'Chelsea', 1969 
                 FROM dual 
                UNION ALL 
               SELECT 'Chelsea', 1970 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1971 
                 FROM dual 
                UNION ALL 
               SELECT 'Manchester United', 1972 
                 FROM dual
              )
SELECT team_name
     , MAX(consecutive_championships) consecutive_championships
     , MAX(startyear) KEEP (dense_rank first order by consecutive_championships desc) startyear
     , MAX(endyear) KEEP (dense_rank first order by consecutive_championships desc) endyear
  FROM (SELECT team_name
             , MIN(year) startyear
             , MAX(year) endyear
             , COUNT(*) consecutive_championships
          FROM (SELECT team_name
                     , year
                     , SUM(x) OVER (PARTITION BY team_name ORDER BY year) gr
                  FROM (select team_name
                             , year
                             , sign(year - lag(year,1,0) OVER (PARTITION BY team_name ORDER BY year) - 1) x
                          FROM champ
                       )
               )
         GROUP BY team_name
                , gr
       )
 GROUP BY team_name
 ORDER BY team_name
;

WITH clause from previous SELECT
SELECT team_name
     , cons_champ
     , year_start
     , year year_end
  FROM (SELECT *
          FROM champ
         MODEL
           DIMENSION BY (ROW_NUMBER() OVER (ORDER BY year) rn)
           MEASURES(year, team_name, 0 year_start, 0 cons_champ, 0 max_cons_champ)
           RULES (year_start[rn]     = DECODE(team_name[CV(rn)], team_name[CV(rn)-1], year_start[CV(rn)-1], year[CV(rn)])
                 ,cons_champ[rn]     = DECODE(team_name[CV(rn)], team_name[CV(rn)-1], cons_champ[CV(rn)-1]+1, 1)
                 ,max_cons_champ[rn] = MAX(cons_champ) OVER (PARTITION BY team_name)
                 )
       )
 WHERE max_cons_champ = cons_champ
 ORDER BY team_name DESC  
;              

TEAM_NAME         CONS_CHAMP YEAR_START   YEAR_END
----------------- ---------- ---------- ----------
Chelsea                    3       1968       1970
Manchester United          5       1961       1965



And here some examples where old school SQL won't solve the problem (aside from writing new functions maybe)

Replace numbers with more than 5 digits with '#' from the OTN-Thread how to update the numbers with characters.

More examples to follow ...


Reference Links
SQL for Modeling

1 
Entries rendered in: 0.28 s




nobody