MySQL

2024.06.13 MySQL활동 서브 쿼리란

정훈5 2024. 6. 13. 08:45

class_32.sql

class_32.sql
0.00MB

subquery란?

서브쿼리(subquery)는 SQL 문장 내에서 다른 SQL 쿼리를 내포하는 구문입니다.

 

서브쿼리의 개념

서브쿼리는 보통 소괄호 () 안에 작성된다.

메인 쿼리(main query) 또는 외부 쿼리(outer query)라고 하는 큰 SQL 쿼리의 일부로 존재합니다.

서브쿼리는 메인 쿼리에 의해 반환된 데이터를 기반으로 추가적인 조건을 적용하거나, 메인 쿼리의 조건을 정의하는 데 사용됩니다.

 

문법에 형태

select * 
from reservation
where name in( select name from customer where address ='서울' );

 

서브쿼리를 사용하는 이유

  1. 복잡성 감소: 복잡한 쿼리를 더 작고 관리하기 쉬운 부분으로 나누어 처리할 수 있습니다.
  2. 재사용성: 같은 서브쿼리를 여러 쿼리에서 재사용할 수 있어, 코드의 중복을 줄이고 유지 보수를 용이하게 합니다.
  3. 명확성: 데이터의 특정 부분에 대해 명확한 조건을 설정할 수 있으며, 읽기 쉽고 이해하기 쉬운 쿼리를 작성할 수 있다.

서브 쿼리의 종류

서브쿼리는 쿼리의 위치가 어디에 있느냐에 따라서 세 가지 종류로 나눌 수 있다.

(1) 중첩 서브 쿼리(Nested Subquery) : WHERE절에 사용하는 서브 쿼리.

(2) 인라인 뷰(Inline View) : FROM절에 사용하는 서브 쿼리.

(3) 스칼라 서브 쿼리(Scalar Subquery) : SELECT절에 사용하는 서브 쿼리. (자주 사용 안함)

(1) 중첩 서브 쿼리(Nested Subquery) - WHERE절에 사용

WHERE 절에 사용되어 외부 쿼리에 필터 조건을 제공합니다.

서브 쿼리의 결과를 이용하여 메인 쿼리의 결과가 결정되는 방식으로 작동합니다.

 

시나리오 쿼리 1 - employees 테이블에서 manager 직원만 출력 하시오.

use employees;

select *
from employees;

select *
from dept_manager
where to_date = '9999-01-01'; -- 현재 종사하고 있다는 뜻

-- 직원 테이블에서 매니저인 사원을 출력 하자. !!
select *
from employees
-- 중첩 서브쿼리 (Nested Subquery)
where emp_no in (select emp_no
				from dept_manager
				where to_date = '9999-01-01');

 

(2) 인라인 뷰(Inline View) - FROM절에 사용

FROM 절에 사용되는 서브 쿼리로, 임시적인 테이블을 생성하여 메인 쿼리에서 참조합니다.

이 방식은 복잡한 데이터 집계나 여러 단계의 데이터 변환을 필요로 하는 조회에서 유용하게 사용됩니다.

 

시니리오 쿼리 2 - 현재 매니저들에 평균 연봉 구하기

-- 시니리오 쿼리 2 - 현재 매니저들에 평균 연봉 구하기
-- From 절에 사용하는 인라인 뷰
-- 현재 다니고 있는 매니저들에 평균 연봉 구하기.
use employees;

select *
from dept_manager
where to_date = '9999-01-01';

select *
from salaries
where emp_no = 10001;

-- 한 직원의 평균 연봉, emp_no 테이블을 group by 처리
select emp_no, avg(salary) as 평균연봉
from salaries as s
group by emp_no;

-- 조건을 추가한다.
-- 여기까지 InLine(인라인)뷰의 결과이다.
select emp_no, 평균연봉
from (select emp_no, avg(salary) as 평균연봉 -- from 안에 있는 select의 emp_no, avg(salary) as 평균연봉을 맨 위에있는 Select에 사용할 수 있다.
	  from salaries as s
	  group by emp_no) as avg_salary
where emp_no = '10001';

-- 인라인뷰, 중첩 서브쿼리를 동시에 사용한다.
select emp_no, 평균연봉
from (select emp_no, avg(salary) as 평균연봉 -- from 안에 있는 select의 emp_no, avg(salary) as 평균연봉을 맨 위에있는 Select에 사용할 수 있다.
	  from salaries as s
	  group by emp_no) as avg_salary -- 인라인 뷰
where emp_no in (select emp_no 
				 from dept_manager -- 중첩 서브쿼리 
                 where to_date = '9999-01-01');

 

위 쿼리는 개념들을 학습하기 위해 작성한 쿼리입니다.

사실 위 결과 집합을 얻기 위해서는 아래와 같은 쿼리가 훨씬 더 효율을 높일 수 있습니다.

 

위와 결과 집합을 INNER JOIN 을 활용해서 만들어 보자.

현재 다니고 있는 매니저들에 평균 연봉 구하기.

select s.emp_no, AVG(s.salary) as '평균연봉'
from dept_manager as d
inner join salaries as s
on d.emp_no = s.emp_no and d.to_date = '9999-01-01'
group by s.emp_no;

 

(3) 스칼라 서브 쿼리(Scalar Subquery) : SELECT절에 사용

Scalar Subquery SELECT 절에서 사용되며 단일 값을 반환합니다. 이 값은 메인 쿼리의 다른 컬럼과 함께 출력될 수 있습니다. 스칼라 서브 쿼리는 각 결과 행에 대해 계산되어 해당 행의 결과에 포함됩니다. 단, 수행속도가 가장 느릴 수 있기 때문에 가능한 지양하는것이 좋습니다.

 

시나리오 쿼리 3 - 각 직원에 평균 연봉 구하기

 

-- 스칼라 서브 쿼리(Scalar Subquery) : SELECT절에 사용
select emp_no as outer_emp_no, (select agv(salary)
								from  salaries
                                where emp_no = outer_emp_no) as 평균연봉
from employees;

 

스칼라 서브쿼리가 각 행에 대해 별도로 실행되기 때문에, 메인 쿼리가 처리해야 할 행의 수가 많을 경우, 전체 쿼리의 실행 시간이 상당히 증가할 수 있습니다. 따라서 다음과 같은 상황에서는 스칼라 서브쿼리의 사용을 재고해야 할 수 있습니다:

  • 데이터 양이 많은 경우
    대량의 데이터를 처리할 때는 스칼라 서브쿼리가 각 행마다 실행되어 성능 저하를 일으킬 수 있습니다.

  • 더 효율적인 대안이 가능한 경우
    때로는 조인(JOIN)이나 임시 테이블, 또는 다른 SQL 최적화 기법을 사용하여 더 효율적으로 동일한 결과를 얻는다.

스칼라 서브쿼리를 사용할 때는 성능을 주의 깊게 고려하고, 필요하다면 쿼리 플랜을 검토하거나 다른 방법을 모색하는 것이 좋습니다.