DB
[MySQL] SubQuery (서브쿼리)
person456
2024. 4. 15. 19:45
* 서브쿼리 (SubQuery)
- 다른 쿼리 내부에 포함되어있는 Select문을 의미함
- 서브쿼리를 포함한 쿼리를 외부 쿼리 (Outer Query) 또는 메인 쿼리라 하며 서브쿼리는 내부쿼리라 부름
- 서브쿼리는 비교연산자 오른쪽에 기술해야하고, 반드시 괄호'()'로 감싸져 있어야만 함
- 서브쿼리는 다중행 연산자, 또는 단일행 연산자와 함께 사용됨
- Select, From, Where, Having, Group by, Order By, Insert의 Values, Update의 Set에 사용 가능
* 서브쿼리의 종류
- 중첩 서브쿼리(Nested Subquery) : Where절에 작성하는 서브쿼리 (단일행, 다중행, 다중컬럼)
- 인라인 뷰 ( Inline-View) : From절에 작성하는 서브쿼리
- 스칼라 서브쿼리 ( Scalar Subquery ) : Select절에 작성하는 서브쿼리
* Nested Subquery
1. 단일행
- 서브쿼리의 결과가 단일행을 리턴
Select department_id, department_name
from departments
where location_id = (
select location_id
from locations
where binary upper(city) = upper('seattle')
);
2. 다중행
- 서브쿼리의 결과가 다중행을 리턴
- 따라서 연산자 역시 IN, ANY, ALL을 사용해야함
- ANY는 결과가 적어도 하나만 만족하면 true임.
- 예를들어 (10, 20, 30)이 반환되었을때 salary > any (서브쿼리)가 되어있다면 10을 기준으로 하게 될 것임
- ALL은 모두 만족한다면 true
- 예를들어 (10,20,30)이 반환되었을 때 salary > all (서브쿼리)라면 모두 만족을 하는 30을 기준으로 하게 될 것임
select employee_id, first_name
from employees
where department_id in (
select department_id
from departments
where location_id = (
select location_id
from locations
where binary upper(city) = upper('seattle')
)
);
* Inline-View
- From절에 사용되는 서브쿼리를 인라인뷰(Inline-View)라고 부름
- 서브쿼리가 From절에 사용되면 View처럼 결과가 동적으로 생성된 테이블로 사용 가능
- 임시적인 뷰이기 때문에 물리적으로 저장되지 않음
- 동적으로 생성된 테이블이기 때문에 Column을 자유로이 참조 가능
select e.id, e.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;
* Scalar Subquery
- SELECT 절에 있는 서브쿼리
- 한개의 행만을 반환
* 서브쿼리의 활용
1. CREATE
- 서브쿼리를 활용하여 테이블 생성이 가능
* 테이블의 이름을 다른 이름으로 변경하여 복사, 데이터 역시 포함되어있음. ( 컬럼 이름은 동일함 )
create table emp_copy
select * from employees;
* 테이블의 이름을 변경하고 데이터는 가져오지 않는 방법 ( 컬럼 이름은 동일 )
create table emp_blank
select * from employees
where 1=0;
2. INSERT
- Values에 들어가는 값에 삽입
insert into emp_blank
select * from employees
where department_id = 80;
3. UPDATE
- set에 위치하는 조건에 사용 가능
update a set sal = sal+500
where sal < (select avg(salary) from b);
4. DELETE
delete from a
where sal < (select avg(salary) from b);