Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

A use for CROSS APPLY

Scott SwankJun 28 2018 — edited Jun 29 2018

I've been playing with CROSS APPLY and a text splitting function. In our case it's named str2tbl(). But it's basically the same thing everyone has written, at least once.

with j as (

    select /*+ materialize */ owner, job_name, repeat_interval

    from dba_scheduler_jobs

    where schedule_type=  'CALENDAR'

    and rownum <= 10

)

select *

from j

    cross apply (

        select column_value

        from table(str2tbl(repeat_interval, ';')) t

        where ltrim(t.column_value) is not null

    ) det;

    

OWNERJOB_NAMEREPEAT_INTERVALCOLUMN_VALUE
YOUJOB1FREQ=HOURLY;INTERVAL=2FREQ=HOURLY
YOUJOB1FREQ=HOURLY;INTERVAL=2INTERVAL=2
YOUJOB2freq=DAILY;freq=DAILY
YOUJOB3FREQ=DAILY;BYHOUR=16FREQ=DAILY
YOUJOB3FREQ=DAILY;BYHOUR=16BYHOUR=16

And then column_value can be decomposed into key/value pairs, via instr and substr.

with j as (

    select /*+ materialize */ owner, job_name, repeat_interval

    from dba_scheduler_jobs

    where schedule_type=  'CALENDAR'

    and rownum <= 10

)

select *

from j

    cross apply (

        select substr(t.column_value,1,instr(t.column_value,'=')-1) as repeat_interval_key,

            substr(t.column_value,instr(t.column_value,'=')+1) as repeat_interval_value

        from table(str2tbl(repeat_interval, ';')) t

        where ltrim(t.column_value) is not null

    ) det;

     

OWNERJOB_NAMEREPEAT_INTERVALREPEAT_INTERVAL_KEYREPEAT_INTERVAL_VALUE
YOUJOB1FREQ=HOURLY;INTERVAL=2FREQHOURLY
YOUJOB1FREQ=HOURLY;INTERVAL=2INTERVAL2
YOUJOB1freq=DAILY;freqDAILY
YOUJOB2FREQ=DAILY;BYHOUR=16FREQDAILY
YOUJOB2FREQ=DAILY;BYHOUR=16BYHOUR16
YOUJOB3freq=MINUTELY; INTERVAL=15;freqMINUTELY
YOUJOB3freq=MINUTELY; INTERVAL=15;INTERVAL15
YOUJOB4freq=MINUTELY; INTERVAL=30;freqMINUTELY
YOUJOB4freq=MINUTELY; INTERVAL=30;INTERVAL30

And that in turn can be pivoted.

with j as (

    select /*+ materialize */ owner, job_name, upper(repeat_interval) repeat_interval

    from dba_scheduler_jobs

    where schedule_type=  'CALENDAR'

    and rownum <= 10

)

select *

from j

    cross apply (

        select substr(t.column_value,1,instr(t.column_value,'=')-1) as repeat_interval_key,

            substr(t.column_value,instr(t.column_value,'=')+1) as repeat_interval_value

        from table(str2tbl(repeat_interval, ';')) t

        where ltrim(t.column_value) is not null

    ) det

    pivot (

        max(repeat_interval_value) as val

        for (repeat_interval_key) in ('FREQ' as freq, 'INTERVAL' as interval, 'BYHOUR' as byhour)

    );

      

OWNERJOB_NAMEREPEAT_INTERVALFREQ_VALINTERVAL_VALBYHOUR_VAL
YOUJOB1FREQ=MINUTELY; INTERVAL=30;MINUTELY30
YOUJOB2FREQ=MINUTELY; INTERVAL=15;MINUTELY15
YOUJOB3FREQ=DAILY;BYHOUR=16DAILY16
YOUJOB4FREQ=DAILY;DAILY
YOUJOB5FREQ=HOURLY;INTERVAL=2HOURLY2

A real use would include all of the other BYMINUTE, etc columns.

Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jul 27 2018
Added on Jun 28 2018
4 comments
800 views