[230707] 서브쿼리, WITH (DAY 8) - 구디아카데미후기 IT국비지원 민경태 강사님

MJ·2023년 7월 10일

수업 TIL🐣💚

목록 보기
8/68

서브쿼리(sub query)

  • 메인쿼리에 포함되는 하위쿼리를 서브쿼리라고 한다.
  • 서브쿼리를 먼저 실행해서 그 결과를 메인쿼리에 전달한다.
  • 한 행에 한 열 즉, 하나의 결과값만을 반환
  • 서브쿼리가 반환하는 칼럼 수와 메인쿼리에서 비교되는 칼럼 수 다르면 오류
  • 서브쿼리 결과가 NULL이면 오류
  • 종류
    1. SELECT 절 : 스칼라 서브쿼리
    2. FROM 절 : 인라인 뷰 (INLINE VIEW)
    3. WHERE 절 : 단일 행 서브쿼리 (결과가 1개), 다중 행 서브쿼리 (결과가 N개)

WHERE 절의 서브쿼리

단일 행 서브쿼리(single row sub query)

  1. 결과가 1행 (1개)
  2. 단일 행 서브쿼리인 경우
    • WHERE 절에서 사용한 칼럼이 PK 또는 UNIQUE 칼럼인 경우
    • 통계 함수를 사용한 경우
  3. 단일 행 서브쿼리 연산자
    • =, !=, >, >=, <, <=
-- 사원번호가 101인 사원의 직업과 동일한 직업을 가진 사원을 조회하기
-- SELECT *
--   FROM EMPLOYEES
--  WHERE JOB_ID = (사원번호가 101인 사원의 직업);
SELECT *
  FROM EMPLOYEES
 WHERE JOB_ID = (SELECT JOB_ID
                   FROM EMPLOYEES
                  WHERE EMPLOYEE_ID = 101);
  • 서브쿼리 결과로 내주는 값이 메인쿼리에 있어야 함 (JOB_ID)

다중 행 서브쿼리(multiple row sub query)

  1. 결과가 N행 (1도 포함)
  2. 다중 행 서브쿼리 연산자
    • IN 서브쿼리의 결과 중에서 하나라도 일치하면 참
    • ANY 서브쿼리의 결과들과 비교한 결과가 하나라도 일치하면 참
    • ALL 서브쿼리의 결과들과 비교한 결과가 모두 일치하면 참
    • EXISTS 서브쿼리의 검색 결과가 하나라도 존재하면 참
  • 다중 행 서브쿼리와 단일 행 비교연산자를 사용하면 오류
-- 부서명이 'IT'인 부서에 근무하는 사원 조회하기
-- SELECT *
--   FROM EMPLOYEES
--  WHERE DEPARTMENT_ID IN (부서명이 'IT'인 부서의 부서번호);
SELECT *
  FROM EMPLOYEES
 WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID
                           FROM DEPARTMENTS
                          WHERE DEPARTMENT_NAME = 'IT');  
-- 서브쿼리의 DEPARTMENT_NAME 칼럼은 중복이 있을 수 있으므로 다중 행 서브쿼리로 처리 (IN)
-- 'Seattle'에서 근무하는 사원 조회하기
SELECT *
  FROM EMPLOYEES
 WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID
                           FROM DEPARTMENTS
                          WHERE LOCATION_ID IN (SELECT LOCATION_ID
                                                 FROM LOCATIONS
                                                WHERE CITY = 'Seattle'));
-- 연봉 가장 높은 사원 조회하기
SELECT *
  FROM EMPLOYEES
 WHERE SALARY = (SELECT MAX(SALARY)
                   FROM EMPLOYEES);

FROM 절의 서브쿼리

  • 인라인 뷰
  • 하나의 테이블처럼 사용되는 쿼리 (뷰는 가상테이블인데 사실상 셀렉트 쿼리문, FROM 뒤에 뷰가 있다 = 뒤에 셀렉트가 있다 = 서브쿼리)
  • 인라인 뷰가 사용되는 주된 이유는 실행 순서
    • FROM 절은 실행순서 1번이라 무조건 먼저 실행 -> ORDER BY는 원래 언제나 꼴등이니까 정렬 먼저 하고 싶을 때 인라인 뷰 씀
    • FROM 서브쿼리 제외하면 다른 것들은 조인으로 바꿔도 됨
    • FROM 서브쿼리는 특별히 쓰는 이유가 있어서 대체 안되는 경우 있음
--연봉 11 ~ 20번째 사원 조회하기
SELECT RN, EMPLOYEE_ID
  FROM (SELECT ROW_NUMBER() OVER(ORDER BY SALARY DESC) AS RN, EMPLOYEE_ID
          FROM EMPLOYEES)
 WHERE RN BETWEEN 11 AND 20;

SELECT 절의 서브쿼리

  • 스칼라 서브쿼리
  • 성능이 좋지 않아서 자주 사용하지 않음
-- 부서번호가 50인 부서에 근무하는 사원번호, 사원명, 부서명 조회하기 (비상관)
SELECT EMPLOYEE_ID
     , FIRST_NAME
     , LAST_NAME
     , (SELECT DEPARTMENT_NAME
          FROM DEPARTMENTS
         WHERE DEPARTMENT_ID = 50) AS DEPT_NAME
  FROM EMPLOYEES
 WHERE DEPARTMENT_ID = 50;
-- 부서번호가 50인 부서에 근무하는 사원번호, 사원명, 부서명 조회하기 (상관)
SELECT E.EMPLOYEE_ID
     , E.FIRST_NAME
     , E.LAST_NAME
     , (SELECT D.DEPARTMENT_NAME
          FROM DEPARTMENTS D
         WHERE D.DEPARTMENT_ID = E.DEPARTMENT_ID
           AND D.DEPARTMENT_ID = 50) AS DEPT_NAME
  FROM EMPLOYEES E;
  • 상관쿼리: 서브 쿼리의 값이 결정되는 데 메인 쿼리의 값(E.DEPARTMENT_ID)을 사용하는 것
  • 비상관쿼리: 서브 쿼리의 값이 결정되는 데 메인 쿼리의 값을 사용하지 않는 것

WITH

  1. 자주 사용하거나 복잡한 쿼리문을 WITH 절의 코드 블록으로 등록시켜 놓을 수 있다.
  2. WITH 절의 코드 블록은 임시로 저장되기 때문에 곧바로 사용해야 한다.
  3. 쿼리문의 가독성이 좋아진다.
-- 부서별 부서번호, 부서명, 연봉총액을 조회하기
-- 1) 조인
SELECT MY.DEPARTMENT_ID
     , MY.TOTAL_SALARY
     , D.DEPARTMENT_NAME
  FROM DEPARTMENTS D INNER JOIN (SELECT DEPARTMENT_ID, SUM(SALARY) AS TOTAL_SALARY
                                   FROM EMPLOYEES
                                  GROUP BY DEPARTMENT_ID) MY
    ON D.DEPARTMENT_ID = MY.DEPARTMENT_ID;
-- 2) WITH
WITH MY_SUBQUERY AS (
    SELECT DEPARTMENT_ID, SUM(SALARY) AS TOTAL_SALARY
      FROM EMPLOYEES
     GROUP BY DEPARTMENT_ID
)
SELECT MY.DEPARTMENT_ID
     , MY.TOTAL_SALARY
     , D.DEPARTMENT_NAME
  FROM DEPARTMENTS D INNER JOIN MY_SUBQUERY MY
    ON D.DEPARTMENT_ID = MY.DEPARTMENT_ID;


🟢 구디아카데미후기 IT국비지원 민경태 강사님 수업 8일차! 🟢
조인이랑 서브쿼리 재밌네 ㅋㅋㅋ 처음엔 헷갈렸는데 하면 할수록 재밌다 (아직까지는)

0개의 댓글