-
개념
- 하나의 SQL 문안에 포함되어 있는 또 다른 SQL문을 말함
- 반드시 괄호로 묶어야 함
- SELECT 안에 SELECT문, INSERT, UPDATE, DELETE 안의 SELECT 문
서브쿼리 사용 가능한 곳
① SELECT 절
② FROM 절
③ WHERE 절
④ HAVING 절
⑤ ORDER BY 절
⑥ DML(INSERT, DELETE, UPDATE)절
* GROUP BY 절은 사용 X종류
1. 동작하는 방식에 따라
1) UN-CORRELATED(비연관) 서브쿼리
- 서브쿼리가 메인쿼리 컬럼을 가지고 있지 않은 형태의 서브쿼리
- 메인쿼리에 서브쿼리가 실행된 결과 값을 제공하기 위한 목적으로 사용
2) CORRELATED(연관) 서브쿼리
- 서브쿼리가 메인쿼리 컬럼을 가지고 있는 형태의 서브쿼리
- 일반적으로 메인쿼리가 먼저 수행된 후에 서브쿼리에서 조건이 맞는지 확인하고자 할 때 사용
2. 위치에 따라
1) 스칼라 서브쿼리- SELECT 에 사용하는 서브쿼
- 서브쿼리 결과를 마치 하나의 컬럼처럼 사용하기 위해 주로 사용
2) 인라인뷰- FROM 절에 사용하는 서브쿼리
- 서브쿼리 결과를 테이블처럼 사용하기 위해 주로 사용
3) WHERE 절 서브쿼리- 가장 일반적인 서브쿼리
- 비교 상수 자리에 값을 전달하기 위한 목적으로 주로 사용(상수항의 대체)
- 리턴 데이터의 형태에 따라 단일행 서브쿼리, 다중행 서브쿼리, 다중컬럼 서브쿼리, 상호연관 서브쿼리로 구분
WHERE 절 서브쿼리 종류
1) 단일행 서브쿼리- 서브쿼리 결과가 1개의 행이 리턴
- 연산자 종류
연산자 의미 = 같다 <> 같지 않다 > 크다 >= 크거나 같다 < 작다 <= 작거나 같다
👉 EMP 테이블에서 전체 직원의 급여 평균보다 높은 평균을 받는 직원의 정보 출력STEP 1) 비교대상(전체 직원 급여 평균) 확인
STEP2) 메인쿼리 비교 상수 자리에 서브쿼리 결과 전달
2) 다중행 서브쿼리- 서브쿼리 결과가 여러 행이 리턴
- ‘=’, ‘>’, ‘<’와 같은 비교 연산자 사용 불가
- 서브쿼리 결과를 하나로 요약하거나 다중행 서브쿼리 연산자 사용
다중행 서브쿼리 연산자
연산자 의미 IN 같은 값을 찾음 > ANY 최소값을 반환함 < ANY 최대값을 반환함 < ALL 최소값을 반환함 > ALL 최대값을 반환함 > ALL(2000, 3000): 최대값(3000)보다 큰 행들 반환
< ALL(2000, 3000): 최소값(2000)보다 작은 행들 반환
> ANY(2000, 3000): 최소값(2000)보다 큰 행들 반환
< ANY(2000, 3000): 최대값(3000)보다 작은 행들 반환👉 다중행 서브쿼리 연산자 오류 (서브쿼리 결과가 여러 개일 경우 = 연산자와 대소 비교 불가)
해결 1: 서브쿼리 결과를 하나의 행의 결과가 되도록 변경
해결 2: 다중행 서브쿼리 연산자로 변경
3) 다중컬럼 서브쿼리- 서브쿼리 결과가 여러 컬럼이 리턴되는 형태
- 메인쿼리와의 비교 컬럼이 2개 이상
- 대소 비교 전달 불가(두 값을 동시에 묶어 대소 비교 불가능)
👉 EMP 테이블에서 부서별 최대 급여자 확인
STEP1) 부서별 최대 급여 확인
STEP2) 메인쿼리에 비교 대상으로 서브쿼리 결과 전달
👉 부서별 최대 급여가 여러 값이 나오므로 비교 시에는 다중행 연산자인 IN을 사용(= 사용시 에러 발생)
4) 상호연관 서브쿼리- 메인쿼리와 서브쿼리의 비교를 수행하는 형태
- 비교할 집단이나 조건은 서브쿼리에 명시(메인쿼리 절에는 서브쿼리 컬럼이 정의되지 않았기 때문에 에러 발생
👉 EMP 테이블에서 부서별로 해당 부서의 평균 급여보다 높은 급여를 받는 사원 정보
에러 발생 다중 컬럼 서브쿼리는 동시 두 컬럼에 대한 대소비교 불가
해결) 대소 비교할 컬럼을 메인쿼리에, 일치 조건을 서브커리에 전달
👉 메인쿼리와 결과적으로 비교해야 할 컬럼은 SAL과 DEPTNO인데 그 중 SAL에 대한 대소비교 전에 먼저 비교할 부서(DETNO) 정보가 확정돼야함
👉 먼저 비교할 DEPTNO 값을 서브쿼리에 전달
👉 메인쿼리에는 서브쿼리의 테이블 정보가 없으므로(순서상 메인쿼리부터 해석) E.DEPTNO = D.DEPTNO 조건은 사용 불가
상호연관 서브쿼리 연산 순서
① 메인쿼리 테이블 READ
② 메인쿼리 WHERE절 확인(SAL 확인)
③ 서브쿼리 테이블 READ
④ 서브쿼리 WHERE절 확인(다시 E1.DEPTNO 요구)
⑤ E1.DEPTNO 값을 서브쿼리의 DEPTNO 컬럼과 비교하여 조건절 완성
⑥ 위 조건에 성립하는 행의 그룹연산 결과 확인(AVG(SAL))
⑦ 위 결과를 메인쿼리에 전달하여 해당 조건을 만족하는 행만 추출
💥 상호연관 서브쿼리 사용 시 GROUP BY 생략 가능
인라인뷰(Inline View)- 쿼리 안의 뷰의 형태로 테이블처럼 조회할 데이터를 정의하기 위해 사용
- 테이블명이 존재하지 않기 때문에 다른 테이블과 조인 시 반드시 테이블 별칭 명시(단독으로 사용 시 불필요)
- WHERE 절 서브쿼리와 다르게 서브쿼리 결과를 메인 쿼리의 어느 절에서도 사용할 수 있음
- 인라인뷰의 결과와 메인쿼리 테이블과 조인할 목적으로 주로 사용
- 모든 연산자 사용 가능
👉 EMP 테이블에서 부서별 최대 급여자를 출력하되, 최대 급여와 함께 출력
💥 인라인뷰에서의 함수에 의한 출력 결과(MAX(SAL))는 컬럼 별칭을 통해 메인 쿼리에 전달!
👉 EMP 테이블에서 부서별로 해당 부서의 평균 급여보다 높은 급여자를 출력하되, 평균 급여와 함께 출력
스칼라 서브쿼리- SELECT 절에 사용하는 쿼리로, 마치 하나의 컬럼처럼 표현하기 위해 사용(단 하나의 출력 대상만 표현 가능)
- 각 행마다 스칼라 서브쿼리 결과가 하나여야 함(단일행 서브쿼리 형태)
- 조인의 대체 연산
- 스칼라 서브쿼리를 사용한 조인 처리 시 OUTER JOIN이 기본(값이 없더라도 생략되지 않고 NULL로 출력됨)
👉 EMP의 각 직원의 사번, 이름과 부서이름을 출력(부서이름을 스칼라 서브쿼리로)
👉 EMP의 각 직원의 사번, 이름, 부서번호, 급여와 함께 급여 총 합을 출력(총 합을 스칼라 서브쿼리로)
👉 서브쿼리와 아우터 조인
👉 KING의 경우 MGR컬럽 값이 NULL이므로 MGR = EMPNO 에 만족하는 E2.ENAME값이 없지만 스칼라 서브쿼리는 무조건 메인쿼리절이 출력하는 대상에 대해 항상 값을 리턴해야 하므로 생략되지 않고 NULL로 출력된
서브 쿼리 주의 사항- 특별한 경우(TOP-N 분석 등)을 제외하고는 서브 쿼리절에 ORDER BY 절을 사용 불가
- 단일 행 서브쿼리와 다중 행 서브쿼리에 따라 연산자의 선택이 중요
👉 서브쿼리에 ORDER BY 전달 시 에러 발생
'CS > SQL' 카테고리의 다른 글
[SQLD] 그룹함수 (0) 2025.02.25 [SQLD] 집합 연산자 (0) 2025.02.24 [SQLD] 표준조인 (0) 2025.02.23 [SQLD] 조인 (0) 2025.02.23 [SQLD] ORDER BY절 (0) 2025.02.22 댓글