LATERAL Inline Views, CROSS APPLY and OUTER APPLY Joins in Oracle Database 12c Release 1 (12.1)
Learn the new variations on inline views and joins available in Oracle 12c.
oracle 12cconfigurationintermediate
by OracleDba
16 views
Learn the new variations on inline views and joins available in Oracle 12c.
123456789101112131415161718192021222324252627282930313233343536373839404142
--drop table employees purge;
--drop table departments purge;
create table departments (
department_id number(2) constraint departments_pk primary key,
department_name varchar2(14),
location varchar2(13)
);
insert into departments values (10,'ACCOUNTING','NEW YORK');
insert into departments values (20,'RESEARCH','DALLAS');
insert into departments values (30,'SALES','CHICAGO');
insert into departments values (40,'OPERATIONS','BOSTON');
commit;
create table employees (
employee_id number(4) constraint employees_pk primary key,
employee_name varchar2(10),
job varchar2(9),
manager_id number(4),
hiredate date,
salary number(7,2),
commission number(7,2),
department_id number(2) constraint emp_department_id_fk references departments(department_id)
);
insert into employees values (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
insert into employees values (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
insert into employees values (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
insert into employees values (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
insert into employees values (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
insert into employees values (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
insert into employees values (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
insert into employees values (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,NULL,20);
insert into employees values (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
insert into employees values (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
insert into employees values (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,NULL,20);
insert into employees values (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
insert into employees values (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
insert into employees values (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
commit;123456789101112131415161718192021222324252627282930313233343536373839
select department_name, employee_name
from departments d
cross join (select employee_name
from employees e
where e.department_id = d.department_id)
order by 1, 2;
ERROR at line 5:
ORA-00904: "D"."DEPARTMENT_ID": invalid identifier
SQL>
select department_name, employee_name
from departments d
cross join lateral (select employee_name
from employees e
where e.department_id = d.department_id)
order by 1, 2;
DEPARTMENT_NAM EMPLOYEE_N
-------------- ----------
ACCOUNTING CLARK
ACCOUNTING KING
ACCOUNTING MILLER
RESEARCH ADAMS
RESEARCH FORD
RESEARCH JONES
RESEARCH SCOTT
RESEARCH SMITH
SALES ALLEN
SALES BLAKE
SALES JAMES
SALES MARTIN
SALES TURNER
SALES WARD
14 rows selected.
SQL>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
select department_name, employee_id, employee_name
from departments d
cross apply (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id)
order by 1, 2, 3;
DEPARTMENT_NAM EMPLOYEE_ID EMPLOYEE_N
-------------- ----------- ----------
ACCOUNTING 7782 CLARK
ACCOUNTING 7839 KING
RESEARCH 7566 JONES
RESEARCH 7788 SCOTT
RESEARCH 7902 FORD
SALES 7698 BLAKE
6 rows selected.
SQL>
select department_name, employee_id, employee_name
from departments d
cross join lateral (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id)
order by 1, 2, 3;
DEPARTMENT_NAM EMPLOYEE_ID EMPLOYEE_N
-------------- ----------- ----------
ACCOUNTING 7782 CLARK
ACCOUNTING 7839 KING
RESEARCH 7566 JONES
RESEARCH 7788 SCOTT
RESEARCH 7902 FORD
SALES 7698 BLAKE
6 rows selected.
SQL>
select department_name, employee_id, employee_name
from departments d
inner join lateral (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id) e
on e.department_id = d.department_id
order by 1, 2, 3;
DEPARTMENT_NAM EMPLOYEE_ID EMPLOYEE_N
-------------- ----------- ----------
ACCOUNTING 7782 CLARK
ACCOUNTING 7839 KING
RESEARCH 7566 JONES
RESEARCH 7788 SCOTT
RESEARCH 7902 FORD
SALES 7698 BLAKE
6 rows selected.
SQL>
-- Create the type and PTF.
create type t_tab as table of number;
/
create or replace function get_tab (p_department_id in number)
return t_tab pipelined
as
begin
if p_department_id != 10 then
for i in (select level as numval
from dual
connect by level <= 2)
loop
pipe row (i.numval);
end loop;
end if;
return;
end;
/
-- CROSS APPLY
select department_name, b.*
from departments d
cross apply (table(get_tab(d.department_id))) b
order by 1, 2;
DEPARTMENT_NAM Result Sequence
-------------- ---------------
OPERATIONS 1
OPERATIONS 2
RESEARCH 1
RESEARCH 2
SALES 1
SALES 2
6 rows selected.
SQL>
-- CROSS JOIN LATERAL
select department_name, b.*
from departments d
cross join lateral (select * from table(get_tab(d.department_id))) b
order by 1, 2;
DEPARTMENT_NAM Result Sequence
-------------- ---------------
OPERATIONS 1
OPERATIONS 2
RESEARCH 1
RESEARCH 2
SALES 1
SALES 2
6 rows selected.
SQL>
-- INNER JOIN LATERAL
select department_name, b.*
from departments d
inner join lateral (select * from table(get_tab(d.department_id))) b
on 1 = 1
order by 1, 2;
DEPARTMENT_NAM Result Sequence
-------------- ---------------
OPERATIONS 1
OPERATIONS 2
RESEARCH 1
RESEARCH 2
SALES 1
SALES 2
6 rows selected.
SQL>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
select department_name, employee_id, employee_name
from departments d
outer apply (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id)
order by 1, 2, 3;
DEPARTMENT_NAM EMPLOYEE_ID EMPLOYEE_N
-------------- ----------- ----------
ACCOUNTING 7782 CLARK
ACCOUNTING 7839 KING
OPERATIONS
RESEARCH 7566 JONES
RESEARCH 7788 SCOTT
RESEARCH 7902 FORD
SALES 7698 BLAKE
7 rows selected.
SQL>
select department_name, employee_id, employee_name
from departments d
left join lateral (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id) e
on e.department_id = d.department_id
order by 1, 2, 3;
DEPARTMENT_NAM EMPLOYEE_ID EMPLOYEE_N
-------------- ----------- ----------
ACCOUNTING 7782 CLARK
ACCOUNTING 7839 KING
OPERATIONS
RESEARCH 7566 JONES
RESEARCH 7788 SCOTT
RESEARCH 7902 FORD
SALES 7698 BLAKE
7 rows selected.
SQL>
-- OUTER APPLY
select department_name, b.*
from departments d
outer apply (table(get_tab(d.department_id))) b
order by 1, 2;
DEPARTMENT_NAM Result Sequence
-------------- ---------------
ACCOUNTING
OPERATIONS 1
OPERATIONS 2
RESEARCH 1
RESEARCH 2
SALES 1
SALES 2
7 rows selected.
SQL>
-- LEFT JOIN LATERAL
select department_name, b.*
from departments d
left join lateral (select * from table(get_tab(d.department_id))) b
on 1=1
order by 1, 2;
DEPARTMENT_NAM Result Sequence
-------------- ---------------
ACCOUNTING
OPERATIONS 1
OPERATIONS 2
RESEARCH 1
RESEARCH 2
SALES 1
SALES 2
7 rows selected.
SQL>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
alter session set events '10053 trace name context forever';
select department_name, employee_name
from departments d
cross join lateral (select employee_name
from employees e
where e.department_id = d.department_id)
order by 1, 2;
alter session set events '10053 trace name context off';
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT "D"."DEPARTMENT_NAME" "DEPARTMENT_NAME",
"E"."EMPLOYEE_NAME" "EMPLOYEE_NAME"
FROM "TESTUSER1"."DEPARTMENTS" "D",
"TESTUSER1"."EMPLOYEES" "E"
WHERE "E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID"
ORDER BY "D"."DEPARTMENT_NAME","E"."EMPLOYEE_NAME"
alter session set events '10053 trace name context forever';
select department_name, employee_id, employee_name
from departments d
cross apply (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id)
order by 1, 2, 3;
ALTER SESSION SET EVENTS '10053 trace name context off';
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT "D"."DEPARTMENT_NAME" "DEPARTMENT_NAME",
"E"."EMPLOYEE_ID" "EMPLOYEE_ID",
"E"."EMPLOYEE_NAME" "EMPLOYEE_NAME"
FROM "TESTUSER1"."DEPARTMENTS" "D",
"TESTUSER1"."EMPLOYEES" "E"
WHERE "E"."SALARY">=2000
AND "E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID"
ORDER BY "D"."DEPARTMENT_NAME","E"."EMPLOYEE_ID","E"."EMPLOYEE_NAME"
alter session set events '10053 trace name context forever';
select department_name, employee_id, employee_name
from departments d
outer apply (select employee_id, employee_name
from employees e
where salary >= 2000
and e.department_id = d.department_id)
order by 1, 2, 3;
alter session set events '10053 trace name context off';
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT "D"."DEPARTMENT_NAME" "DEPARTMENT_NAME",
"E"."EMPLOYEE_ID" "EMPLOYEE_ID",
"E"."EMPLOYEE_NAME" "EMPLOYEE_NAME"
FROM "TESTUSER1"."DEPARTMENTS" "D",
"TESTUSER1"."EMPLOYEES" "E"
WHERE "E"."DEPARTMENT_ID"(+)="D"."DEPARTMENT_ID"
AND "E"."SALARY"(+)>=2000
ORDER BY "D"."DEPARTMENT_NAME","E"."EMPLOYEE_ID","E"."EMPLOYEE_NAME"
alter session set events '10053 trace name context forever';
select department_name, b.*
from departments d
outer apply (table(get_tab(d.department_id))) b
order by 1, 2;
alter session set events '10053 trace name context off';
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT "D"."DEPARTMENT_NAME" "DEPARTMENT_NAME",
"VW_LAT_D4FD8C38"."COLUMN_VALUE_0" "COLUMN_VALUE"
FROM "TESTUSER1"."DEPARTMENTS" "D",
LATERAL( (SELECT VALUE(KOKBF$0) "COLUMN_VALUE_0"
FROM TABLE("TESTUSER1"."GET_TAB"("D"."DEPARTMENT_ID")) "KOKBF$0"))(+) "VW_LAT_D4FD8C38"
ORDER BY "D"."DEPARTMENT_NAME","VW_LAT_D4FD8C38"."COLUMN_VALUE_0"Please to add comments
No comments yet. Be the first to comment!