h5.(1)스칼라 서브쿼리
쿼리에 내장된또다른쿼리 블록을서브쿼리라고하는데 그중에서 함수처럼 한레코드당 정확히 하나의 값만을 리턴하는 서브쿼리를 '스칼라 서브쿼리' 라고 한다.
스칼라 서브쿼리는 주로 select-list에서 사용되지만 몇 가지 예외사항을 뺀다면 컬럼이 올 수 있는 대부분 위치에서 시용 가능하다.
select empno, ename, sal, hiredate
,(select, d.dname from dept d where d.deptno=e.deptno) dname
from emp e
where sal >= 2000
아래 Outer 조인문과 100% 같은 결과를 낸다. dept와 조인에 실패하는 emp 레코드가 있다면 dname으로 null 값이 출력
elect /*+ ordered use_nl(d) */ empno, ename, sal, hiredate, dname
from emp e, dept d
where d.deptno(+)=e.deptno and sal >= 2000;
h5.(2)스칼라 서브쿼리의 캐싱 효과
스칼라 서브쿼리 수행횟수를 최소화하려고 그 입력 값과 출력 값을 내부 캐시 (Query Execution Cache)에 저장해 둔다.
스칼라 서브쿼리가 수행될 때면 일단 '입력 값' 을 캐시에서 찾아 보고 거기 있으면 저장된 '출력 값'을리턴한다. 캐시에서 찾지 못할때만쿼리를수행하며,
결과는 버리지 않고 캐시에 저장해 둔다.
select empno, ename, sal, hiredate
,(select d.dname -> 출력갑
from dept d
where d.deptno=e.deptno -> 입력값
)
from emp e
where sal >= 2000
반복 수행되는 함수 때문에 쿼리 성능이 크게 저하될 때, 아래와 같이 함수에 스칼라 서브쿼리를 덧씌움으로써 호출 횟수를 줄이는 튜닝 사례
select empno, ename, sal, hiredate
,(select get_name(deptno) from dual) dname
from emp e
where sal >= 2000
h5.(3)두 개 이상의 값을 리턴하고 싶을 때
select d.deptno, d.dname, avg_sal, min_sal, max_sal
from dept d
,(select deptno, avg(sal) avg_sal, min(sal) min_sal, max(sal) max_sal
from emp group by deptno) e
where e.deptno(+)=d.deptno
and d.loc = 'CHICAGO'
사원(emp) 태이블 전제를 다 읽어야 하는 비효율
select d.deptno, d.dname
,(select avg(sal), min(sal), max(sal) from emp where deptno=d.deptno)
from dept d
where d.loc = 'CHICAGO'
스칼라 서브쿼리는 한 레코드당 하나의 값만 리턴한다.
select d.deptno, d.dname
,(select avg(sal) from emp where deptno=d.deptno) avg_sal
,(select min(sal) from emp where deptno=d.deptno) min_sal
,(select max(sal) from emp where deptno=d.deptno) max_sal
from dept d
where d.loc = 'CHICAGO'
emp의 같은 범위를 반복적으로 접근하는 비효율
select d.deptno, d.dname
,to_number(substr(sal, 1, 7) avg_sal
,to_number(substr(sal, 8, 7) min_sal
,to_number(substr(sal, 15) max_sal
from (
select d.deptno, d.name
,(select lpad(avg(sal), 7) || lpad(min(sal), 7) || max(sal)
from emp where deptno=d.deptno) sal
from dept d
where d.loc = 'CHICAGO'
)
substr 함수로 분리
create or replace type sal_type as object
( avg_sal number, min_sal number, max_sal number)
select deptno, dname
, a.avl.svg_sal, a.sal.min_sal, a.sal.max_sal
from (
select d.deptno, d.name
,(select sal_type( avg(sal), min(sal), max(sal) )
from emp where deptno=d.deptno) sal
from dept d
where d.loc = 'CHICAGO'
) a
오브젝트 TYPE 사용