Search
Duplicate
😀

02. SubQuery

태그

서브 쿼리(Subquery)

서브 쿼리(subquery)란 다른 쿼리 내부에 포함되어 있는 SELECT 문을 의미한다
서브 쿼리를 포함하고 있는 쿼리를 외부 쿼리(outer query)또는 메인 쿼리라고 부르며, 서브 쿼리는 내부 쿼리(inner query)라고도 부른다.
서브 쿼리는 비교 연산자의 오른쪽에 기술해야 하고 반드시 괄호(())로 감싸져 있어야만 한다

서브 쿼리의 종류

중첩 서브 쿼리(Nested Subquery) - WHERE 문에 작성하는 서브 쿼리
1.
단일 행 (=, >, < ,etc)
2.
복수(다중) 행 (in, any, all)
3.
다중 컬럼
인라인 뷰(Inline View) - FROM 문에 작성하는 서브 쿼리
스칼라 서브 쿼리(Scalar Subquery) - SELECT 문에 작성하는 서브 쿼리

서브 쿼리(Subquery)

주의사항
서브 쿼리는 반드시 ( ) 로 감싸야 한다.
서브 쿼리는 단일 행 또는 다중 행 비교 연산자와 함께 사용된다.
서브 쿼리가 사용 가능한 곳
SELECT
FROM
WHERE
HAVING
ORDER BY
INSERT 문의 VALUES
UPDATE 문의 SET

서브 쿼리의 종류 - Nested Subquery

사번이 100인 사원의 부서 이름
출력해야 할 결과인 department_name은 departments table에 존재하지만, 지문상 알 수 있는 data인 employee_id는 employees table에 존재한다. 서브 쿼리를 통해 해결하거나 join을 이용해서 해결할 수 있다. join의 경우 쿼리가 복잡해 지거나 카테시안곱으로 인한 속도 저하가 올 수 있다. (But 일반적으로는 join이 서브쿼리보다 빠르다 → 서브쿼리는 추가적인 도구)
// 조인 select d.department_name from employees e join departments d on e.department_id = d.department_id where e.employee_id = 100; // 서브쿼리 select department_name from departments where department_id = ( select department_id from employees where employee_id = 100 );
SQL
복사

서브 쿼리 종류 - 인라인 뷰(Inline View)

FROM 절에 사용되는 서브 쿼리를 인라인 뷰(Inline View)라 한다.
서브 쿼리가 FROM절에 사용되면 뷰(View)처럼 결과가 동적으로 생성된 테이블로 사용 가능
임시적인 뷰이기 때문에 데이터베이스에는 저장되지 않는다.
동적으로 생성된 테이블이기 때문에 column을 자유롭게 참조 가능
-- 인라인뷰(Inline View) -> from 절에 붙이는 서브쿼리 -- 모든 사원의 평균 급여보다 적게 받는 사원들과 -- 같은 부서에서 근무하는 사원의 사번, 이름, 급여, 부서번호 select e.employee_id, e.first_name, e.salary, e.department_id from ( select distinct department_id from employees where salary < (select avg(salary) from employees) ) d join employees e on d.department_id = e.department_id;
SQL
복사
활용 - TopN 질의, limit
-- TopN 질의 -- 모든 사원의 사번, 이름, 급여를 출력.(단 아래의 조건 참조) -- 1. 사원 정보를 급여순으로 정렬. -- 2. 한 페이지당 5명이 출력. -- 3. 현재페이지가 3페이지라고 가정. (급여 순 11등 ~ 15등까지 출력) set @pageno = 3; -- 변수 설정 select b.rn, b.employee_id, b.first_name, b.salary from ( select @rownum := @rownum + 1 as rn, a.* from ( select employee_id, first_name, salary from employees order by salary desc ) a, (select @rownum := 0) tmp -- join키워드 생략, 카테시안 곱으로 tmp 테이블 생성 ) b where b.rn > (@pageno * 5 - 5) and b.rn <= (@pageno * 5); -- MySQL은 limit로 해결. select employee_id, first_name, salary from employees order by salary desc limit 10, 5; select a.* from ( select @rownum := @rownum + 1 as rn, employee_id, first_name, salary from employees e, (select @rownum := 0) tmp order by salary desc ) a limit 10, 5;
SQL
복사

서브 쿼리 - Scalar Subquery

메인 쿼리에서 만들어진 값을 서브 쿼리에서 활용할 수 있음
하지만 성능적인 측면에서는 좋지 않아서 잘 활용 X
-- 부서번호가 50인 부서의 총급여, 60인 부서의 평균급여, -- 90인 부서의 최고급여, 90인 부서의 최저급여 select (select sum(salary) from employees where department_id = 50) sum50, (select avg(salary) from employees where department_id = 60) avg60, (select max(salary) from employees where department_id = 90) max90, (select min(salary) from employees where department_id = 90) min90 from dual; -- 컬럼으로 뽑아내기
SQL
복사

서브 쿼리의 활용

서브 쿼리를 이용하여 create, insert, update, delete 작업을 수행할 수 있다.
-- 서브쿼리를 이용한 create. -- employees table을 emp_copy라는 이름으로 복사(컬럼 이름 동일). create table emp_copy select * from employees; -- employees table의 구조만 emp_blank라는 이름으로 생성(컬럼 이름 동일). create table emp_blank select * from employees where 1 = 0; -- 50번 부서의 사번(eid), 이름(name), 급여(sal), 부서번호(did)만 emp50이라는 이름으로 생성. create table emp50 select employee_id eid, first_name name, salary sal, department_id did from employees where department_id = 50; -- 서브쿼리를 이용한 insert. -- employees table에서 부서번호가 80인 사원의 모든 정보를 emp_blank에 insert insert into emp_blank select * from employees where department_id = 80; -- 서브쿼리를 이용한 update. -- employees table의 모든 사원의 평균 급여보다 적게 받는 emp50 table의 사원의 급여를 500 인상. update emp50 set sal = sal + 500 where sal < (select avg(salary) from employees); -- 서브쿼리를 이용한 delete. -- employees table의 모든 사원의 평균 급여보다 적게 받는 emp50 table의 사원은 퇴사. delete from emp50 where sal < (select avg(salary) from employees);
SQL
복사