본문 바로가기
공부/Database

서브쿼리 사용 예시

by 무심한고라니 2020. 12. 12.

쿼리에 대해선 관련 글을 읽어도 비교적 머리에 잘 안 들어오는 경우가 많았기에 프로젝트를 하며 접하는 쿼리 예시들을 하나씩 남겨볼까 합니다. 성능 등 심화된 부분은 전혀 아는 바가 없기에 내용에 대한 오류나 개선사항 등이 있다면 댓글을 남겨주시면 감사하겠습니다.

 

_____

 

서브쿼리(Sub-Query)[1][2]란 SQL 문장 안에서 보조로 사용되는 또 다른 SELECT문을 의미한다. 최종 결과를 출력하는 쿼리를 메인 쿼리라고 한다면, 이를 위한 중간 단계 혹은 보조 역할을 하는 SELECT문을 서브 쿼리라 한다. 따라서 하나의 SQL문을 기준으로 메인 쿼리를 제외한 나머지 모든 SELECT문을 서브 쿼리로 보면 되며, 이는 여러 개 사용할 수 있다.

 

한편 서브쿼리는 다양한 형태로 사용되는데, SELECT뿐 아니라 INSERT, UPDATE 문에서도 사용할 수 있고 위치 또한 FROM, WHERE 절 등에서 모두 사용 가능하다. 정리하자면 다음과 같이 구분할 수 있다.

 

  1. 메인 쿼리와의 연관성에 따라[3]
    • 연관성 없는(Noncorrelated) 서브 쿼리
    • 연관성 있는 서브 쿼리
  2. 형태에 따라
    • 일반 서브 쿼리(SELECT절)[4]
    • 인라인 뷰(FROM 절)
    • 중첩 쿼리(WHERE 절)

 

프로젝트를 하며 스칼라 서브 쿼리, 인라인 뷰, 중첩 쿼리 모두 사용하거나 본 것 같다. 이에 대해 간략하게 정리한다.

 

-- 스칼라 서브쿼리
-- 하나의 레코드만 리턴이 가능하며, 일치하는 데이터가 없더라도 NULL을 리턴할 수 있다.


-- 인라인 뷰
-- 원래 FROM 절에는 테이블이나 뷰가 오지만, 서브쿼리를 FROM 절에 사용할 수 있다.
-- 뷰를 해체하면 하나의 독립적인 SELECT문이므로 FROM 절에 사용하는 서브 쿼리도 하나의 뷰로 볼 수 있어, 인라인 뷰라는 이름이 붙은 것이다.
SELECT a.employee_id
     , a.emp_nm
     , b.department_id
     , b.department_nm
  FROM employees a
     , departments b
     , (SELECT AVG(c.salary) AS avg_salary
          FROM departments b
             , employees c
         WHERE b.parent_id     = '90' -- 기획부
           AND b.department_id = c.department_id) d
 WHERE a.department_id = b.department_id
   AND a.salary > d.avg_salary;

-- 서브 쿼리
-- 주로 경험상 같은 테이블을 조회하지만 메인 테이블의 키값 하나를 확정할 때(ex. 일자) 사용했다.
SELECT emp_id
     , emp_nm
  FROM employees
 WHERE hire_dd = (SELECT MAX(hire_dd)
                    FROM employees);

 

 

_____

1. 관계형 데이터베이스에서 테이블 간의 관계를 맺는 방법엔 조인과 서브쿼리가 있다.

2. 서브 쿼리는 메인 쿼리의 컬럼을 모두 사용할 수 있지만 메인 쿼리는 서브 쿼리의 컬럼을 사용하지 못한다.

3. 메인 쿼리와의 연관성이 있다는 것은 메인 테이블과 조인 조건이 걸린 서브 쿼리를 말한다.

-- 연관성 없는 서브 쿼리
SELECT count(*)
  FROM employees
 WHERE salary >= (SELECT AVG(salary)
                    FROM employees);

-- 연관성 있는 서브 쿼리
-- 예1
SELECT a.department_id
     , a.department_nm
  FROM departments a
 WHERE EXISTS (SELECT 1
                 FROM job_history b
                WHERE a.department_id = b.department_id);

-- 예2
-- 각 서브쿼리가 독립적이므로 별칭을 b로 통일해도 무방하다.
SELECT a.employee_id
     , (SELECT b.emp_nm
          FROM employees b
         WHERE a.employee_id = b.employee_id) AS emp_nm
     , a.department_id
     , (SELECT b.department_nm
          FROM departments b
         WHERE a.department_id = b.department_id) AS dep_nm
  FROM job_history a;

4. 스칼라 서브쿼리라고도 한다.

 

_____

참고자료

 

 

 

 

'공부 > Database' 카테고리의 다른 글

조회 성능  (0) 2024.11.05
Database 경험  (0) 2024.11.05
JOIN과 Sub-Query의 차이  (0) 2021.04.17
LISTAGG Function  (0) 2021.01.12

댓글