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);