[홍쌤의 데이터랩, SQLD n과목 완벽 정리] 영상를 개인이 정리하여 [원작자의 허가 이후] 올린 글이며,
[개인이 추가로 정리한 내용]이 포함되어 있습니다.
목차
서브 쿼리 (Sub Query)
- 쿼리 안에 포함되어있는 또 다른 쿼리
- 반드시 괄호로 묶어야 함
- GROUP BY절에 사용 불가
서브 쿼리의 분류
1. 동작 방식에 따른 분류
1) UN-CORRNLATED(비연관) 서브 쿼리
- 서브 쿼리가 메인쿼리의 컬럼을 가지고 있지 않은 형태
- 메인쿼리에 서브 쿼리의 결과 값을 제공하기 위해 사용
2) CORRNLATED(연관) 서브 쿼리
- 서브 쿼리가 메인쿼리의 컬럼을 가지고 있는 형태
- 일반적으로 메인쿼리의 수행 이후, 서브 쿼리에서 조건 확인을 위해 사용
2. 위치에 따른 분류
1) 스칼라 서브 쿼리
- SELECT절에 사용하는 서브 쿼리
- 주로 서브 쿼리 결과를 하나의 컬럼 처럼 사용하기 위해 사용
=> 단일행 서브 쿼리 형태여야 함
- 조인의 대체 연산
- 스칼라 서브 쿼리를 사용한 JOIN 처리시, OUTER JOIN이 기본 (값이 없더라도 생략되지 않고 NULL로 출력)
e.g.
1) SELF JOIN - LEFT OUTER JOIN 형태
SELECT E1.ENAME AS 사원,
(SELECT E2.ENAME
FROM EMP E2
WHERE E1.MGR = E2.EMPNO) AS 관리자
FROM EMP E1;
사원의 관리자가 없는 (NULL인)경우,
WHERE E1.MGR = E2.EMPNO 조건에서 조건을 만족하지 않으므로 INNER JOIN 형태를 띄지만,
메인 쿼리문에서 다시 포함시키므로 OUTER JOIN 동작과 유사해짐
정확히는, 메인쿼리가 왼쪽에 존재하므로 LEFT OUTER JOIN 동작과 유사해짐
2) 인라인 뷰
- FROM절에 사용하는 서브 쿼리
- 주로 서브 쿼리 결과를 테이블처럼 사용하기 위해 사용 (메인 쿼리 테이블과의 JOIN)
- 테이블명이 존재하지 않으므로 JOIN 시 Alias 필요
- WHERE절 서브 쿼리와 다르게 서브 쿼리 결과를 메인 쿼리의 모든 절에 사용할 수 있음
- 모든 연산자 사용 가능
1) 에러 구문 - 단일행과 그룹의 대소 비교
SELECT *
FROM EMP E, (SELECT AVG(SAL) AS AVG_SAL
FROM EMP
GROUP BY DEPTNO) I
WHERE E.SAL > I.AVG_SAL; -- error
2) 올바른 구문 - JOIN 활용
SELECT *
FROM EMP E, (SELECT DEPTNO , AVG(SAL) AS AVG_SAL
FROM EMP
GROUP BY DEPTNO) I
WHERE E. DEPTNO = I. DEPTNO
AND E.SAL > I.AVG_SAL; -- 위 구문에서 필요했던 조건
3) WHERE절 서브 쿼리
- 특별한 명칭 없음
- 주로 비교 상수 자리에 값을 전달하기 위해로 사용 (상수항 대체)
- 리턴 데이터의 형태에 따라 단일행/다중행/다중컬럼/상호연관 서브 쿼리로 구분
3-1) 단일 행 서브 쿼리
- 서브 쿼리 결과로 단일 행이 리턴
- 비교연산자 {=, <> (같지 않다), >, >=, <, <= 등}와 사용
e.g.
SELECT *
FROM T1
WHERE PRICE > (SELECT PRICE
FROM T2
WHERE NO = 3);
3-2) 다중 행 서브 쿼리
- 서브 쿼리 결과로 다중 행이 리턴
- 비교 연산자와 사용 불가능
- 단일 결과(행)로 바꾸거나, 다중행 서브 쿼리 연산자와 {IN, ANY, ALL 등}사용
해당 식들은 WHERE NO = IN(1,2,3)과 같이 단일행으로 처리 됨
> ALL() : 모든 원소 보다 큰
> ALL(1,2,3) : 3(최댓값)보다 큰
< ALL() : 모든 원소 보다 작은
<ALL(1,2,3) : 1(최솟값)보다 작은
> ANY() : 원소 중 어떤 값 보다 큰
>ANY(1,2,3) : 1(최솟값)보다 큰
< ANY() : 원소 중 어떤 값 보다 작은
<ANY(1,2,3) : 3(최댓값)보다 작은
e.g.
1) 다중행 -> 단일행 서브 쿼리로 변경
SELECT *
FROM T1
WHERE PRICE > (SELECT MIN(PRICE)
FROM T2
WHERE CATEGORY = 'BOOK');
2) 다중행 서브 쿼리 연산자 사용
SELECT *
FROM T1
WHERE PRICE > ANY(SELECT PRICE
FROM T2
CATEGORY = 'BOOK');
3-3) 다중 컬럼 서브 쿼리
- 서브 쿼리 결과로 다중 컬럼이 리턴
- 동등 비교 가능, 대소 비교 전달 불가 (컬럼이 2개 이상이므로, 두 값 동시에 대소비교 불가)
e.g.
1) 부서별 최대 급여
SELECT DEPTNO, MAX(SAL)
FROM EMP
GROUP BY DEPTNO;
해당 쿼리문은 그룹화 이후 집계하기 때문에, SELECT문에 최대 급여자(ENAME) 컬럼 추가 불가능
2) 부서별 최대 급여 및 최대 급여자
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE (DEPTNO, SAL) IN (SELECT DEPTNO, MAX(SAL) -- 서브 쿼리에 컬럼이 2개
FROM EMP
GROUP BY DEPTNO);
3-4) 상호 연관 서브 쿼리
- 메인쿼리와 서브 쿼리의 비교를 수행하는 형태
- 비교할 집단이나 조건은 서브 쿼리에 명시 (메인쿼리에는 서브 쿼리 컬럼이 정의되지 않았기 때문에 에러)
e.g.
부서별 평균급여보다 높은 급여를 받는 사원 (대소 비교 필요)
1) 에러 구문 - 다중컬럼 서브 쿼리의 대소비교 수행
SELECT ENAME, SAL, DEPTNO
FROM EMP
WHERE (DEPTNO, SAL) > (SELECT DEPTNO, AVG(SAL) -- 대소 비교 불가
FROM EMP
GROUP BY DEPTNO);
2) 올바른 구문 - 상호연관 서브 쿼리 (대소 비교할 컬럼을 메인쿼리, 일치 조건을 서브 쿼리에 전달)
SELECT ENAME, SAL, DEPTNO
FROM EMP E1
WHERE SAL > (SELECT AVG(SAL)
FROM EMP E2
WHERE E1.DEPTNO = E2.DEPTNO -- 일치 조건
-- AND E1.XX = E2.XX => 추가 조건 기입
GROUP BY DEPTNO); -- GROUP BY절 생략 가능
'CS - 강의, 서적 > [SQLD] 홍쌤의 데이터랩' 카테고리의 다른 글
[SQLD] 2-17~18. SQL1 (DML, TCL, LOCK) (0) | 2024.09.21 |
---|---|
[SQLD] 2-10. 집합 연산자 (UNION, UNION ALL, INTERSECT, MINUS) (1) | 2024.09.18 |
[SQLD] 2-7~8. 조인 (USING/ON, Oracle/ANSI 표준별 조인) (1) | 2024.09.16 |
[SQLD] 2-2~6. SQL (Alias, DUAL Table, SELECT, FROM, WHERE, GROUP/ORDER BY, HAVING) (0) | 2024.09.16 |
[SQLD] 2-1. 관계형 데이터베이스 개요 (데이터 무결성, SQL) (0) | 2024.09.16 |