MySQL

서브 쿼리란

H_u 2024. 6. 24. 10:19
728x90
반응형
SMALL

1. 개념

subquery란?

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

 

서브쿼리의 개념

서브쿼리는 보통 소괄호 () 안에 작성되며, 메인 쿼리(main query) 또는 외부 쿼리(outer query)라고 하는 더 큰 SQL 쿼리의 일부로 존재. 서브쿼리는 메인 쿼리에 의해 반환된 데이터를 기반으로 추가적인 조건을 적용하거나, 메인 쿼리의 조건을 정의하는 데 사용된다.

 

문법에 형태 살펴 보기

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

 

서브쿼리를 사용하는 이유

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

2. 서브 쿼리의 종류

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

  1. 중첩 서브 쿼리(Nested Subquery) : WHERE절에 사용하는 서브 쿼리.
  2. 인라인 뷰(Inline View) : FROM절에 사용하는 서브 쿼리.
  3. 스칼라 서브 쿼리(Scalar Subquery) : SELECT절에 사용하는 서브 쿼리.

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

WHERE 절에 사용되어 외부 쿼리에 필터 조건을 제공한다. 서브 쿼리의 결과를 이용하여 메인 쿼리의 결과가 결정되는 방식으로 작동한다.

시나리오 쿼리 1 - employees 테이블에서 manager 직원만 출력 하시오.
-- 사전 데이터 확인
SELECT *
FROM employees;

SELECT *
FROM dept_manager
WHERE to_date = '9999-01-01';

-- 직원 테이블에서 매니저인 사원을 출력 하자. !!
SELECT *
FROM employees
WHERE emp_no IN (
		SELECT emp_no
		FROM dept_manager
		WHERE to_date = '9999-01-01');

 

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

FROM 절에 사용되는 서브 쿼리로, 임시적인 테이블을 생성하여 메인 쿼리에서 참조한다. 이 방식은 복잡한 데이터 집계나 여러 단계의 데이터 변환을 필요로 하는 조회에서 유용하게 사용된다.

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

SELECT * FROM dept_manager WHERE to_date = '9999-01-01';
SELECT * FROM salaries WHERE emp_no = 10001;

-- 한 직원의 평균 연봉, emp_no 그룹바이 처리
SELECT emp_no, AVG(salary) AS 평균연봉
FROM salaries AS s
GROUP BY emp_no;

-- 인라인뷰를 사용했던 개념
SELECT emp_no, 평균연봉
FROM (SELECT emp_no, AVG(salary) AS 평균연봉
        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 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')

 

위 쿼리는 개념들을 학습하기 위해 작성한 쿼리이다. 사실 위 결과 집합을 얻기 위해서는 아래와 같은 쿼리가 훨씬 더 효율을 높일 수 있다.

SELECT s.emp_no, AVG(salary) AS 평균연봉
FROM salaries AS s
JOIN dept_manager AS dm ON s.emp_no = dm.emp_no 
	AND dm.to_date = '9999-01-01'
GROUP BY emp_no;

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

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

시나리오 쿼리 3 - 각 직원에 평균 연봉 구하기
SELECT emp_no AS outer_emp_no, (SELECT AVG(salary)
                                    FROM salaries
                                    WHERE emp_no = outer_emp_no) AS 평균연봉
FROM employees

 

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

  • 데이터 양이 많은 경우: 대량의 데이터를 처리할 때는 스칼라 서브쿼리가 각 행마다 실행되어 성능 저하를 일으킬 수 있다.
  • 더 효율적인 대안이 가능한 경우: 때로는 조인(JOIN)이나 임시 테이블, 또는 다른 SQL 최적화 기법을 사용하여 더 효율적으로 동일한 결과를 얻을 수 있다.

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

728x90
반응형
SMALL

'MySQL' 카테고리의 다른 글

제 2정규화(Second Normal Form, 2NF)  (0) 2024.06.24
제 1정규화(First Normal Form, 1NF)  (0) 2024.06.24
쇼핑몰과 카테고리 2단계  (0) 2024.06.24
쇼핑몰과 카테고리 1단계  (0) 2024.06.24
블로그 서비스의 DB 구축  (0) 2024.06.24