728x90
반응형
서브쿼리
SQL문을 실행하는 데 필요한 데이터를 추가로 조회하기 위해 SQL문 내부에서 사용하는 SELECT문
SELECT문 외에도 INSERT, UPDATE, DELETE, CREATE문 등 다양한 SQL문에서 서브쿼리 사용
-- SELECT문의 WHERE절에 SUBQUERY (메인쿼리 내의 서브쿼리)
SELECT 열
FROM 테이블
WHERE 조건식 ( SELECT 열
FROM 테이블
WHERE 조건식 )
✨ 서브쿼리의 특징
- 연산자와 같은 비교 또는 조회 대상의 오른쪽에 놓이며
괄호
로 묶어 사용 - 특수한 경우 제외, 대부분의 서브쿼리는
ORDER BY절
을 사용할 수 없음 - 서브쿼리 SELECT절의 열은 메인쿼리의 비교 대상과 같은 자료형과 같은 개수로 지정
- 메인쿼리 연산자 종류와 서브쿼리 SELECT문 결과 행 수는 호환 가능해야 함
단일행 서브쿼리
실행 결과가 하나
single-row subquery : 실행 결과가 단 하나의 행으로 나오는 서브쿼리
단일행 연산자(>, >=, =, <=, <, <>, ^=, !=)를 사용하여 값 비교
-- JONES의 급여보다 높은 급여를 받는 사원 정보 (서브쿼리 이용)
SELECT *
FROM EMP
WHERE SAL > (SELECT SAL
FROM EMP
WHERE ENAME = 'JONES'); -- 참고로, 이때 JONES라는 이름이 여러 개 존재하면 에러발생
-- 서브쿼리 결과 값이 날짜형 (SCOTT보다 빨리 입사한 사원 목록)
SELECT *
FROM EMP
WHERE HIREDATE < (SELECT HIREDATE
FROM EMP
WHERE ENAME = 'SCOTT'); -- 참고로, 이때 JONES라는 이름이 여러 개 존재하면 에러발생
다중행 서브쿼리
실행 결과가 여러 개
multiple-row subquery : 실행 결과 행이 여러 개로 나오는 서브쿼리
다중행 연산자(IN, ANY, SOME, ALL, EXISTS)를 사용하여 값 비교
IN
: 하나라도 일치한 데이터가 있다면 TRUEANY
,SOME
: 만족하는 결과가 하나 이상이면 TRUEALL
: 결과가 모두 만족하면 TRUEEXISTS
: 결과가 존재하면 TRUE (행이 1개 이상이면 TRUE)
-- <IN> 부서별 최고 급여와 동일한 급여를 받는 사원 정보
SELECT *
FROM EMP
WHERE SAL IN (SELECT MAX(SAL) FROM EMP GROUP BY DEPTNO);
-- <SOME> 등가 비교 연산자(=)와 ANY, SOME을 함께 사용하면 IN 연산자와 같은 기능 수행
SELECT *
FROM EMP
WHERE SAL = SOME (SELECT MAX(SAL) FROM EMP GROUP BY DEPTNO);
-- <ANY> 등가 비교 연산자가 아닌 대소 비교 연산자와 ANY를 함께 사용하면?
-- < ANY : 부서 30 중 최대값보다 적은 급여를 가진 사원을 찾게 됨
-- > ANY : 부서 30 중 최소값보다 높은 급여를 가진 사원을 찾게 됨
SELECT *
FROM EMP
WHERE SAL < ANY (SELECT SAL FROM EMP WHERE DEPTNO = 30);
-- <ALL> 부서 30 중 최대 급여보다 더 많은 급여를 받는 사원 출력
SELECT *
FROM EMP
WHERE SAL > ALL (SELECT SAL FROM EMP WHERE DEPTNO = 30);
-- <EXISTS> 부서50이 있으면 EMP 전체 출력
SELECT *
FROM EMP
WHERE EXISTS (SELECT DNAME FROM DEPT WHERE DEPTNO = 50);
다중열 서브쿼리
비교할 열이 여러 개
multiple-column subquery : 서브쿼리의 SELECT절에 비교할 데이터를 여러 개 지정하는 방식 (복수열 서브쿼리)
SELECT *
FROM EMP
WHERE (DEPTNO, SAL) IN (SELECT DEPTNO, MAX(SAL) FROM EMP GROUP BY DEPTNO);
FROM절 서브쿼리
= 인라인 뷰
특정 테이벌 전체 데이터가 아닌 SELECT문을 통해 일부 데이터를 먼저 추출 후 사용
SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME, D.LOC
FROM (SELECT * FROM EMP WHERE DEPTNO = 10) E,
(SELECT * FROM DEPT) D
WHERE E.DEPTNO = D.DEPTNO;
FROM절에 직접 테이블을 명시하여 사용하기에 데이터 규모가 크거나 불필요한 열이 많을 때, 일부 행과 열만 사용하고자 할 때 사용
WITH절
FROM절에 너무 많은 서브쿼리를 지정하면 가독성이나 성능이 떨어지기 때문에 사용
WITH
[별칭1] AS (SELECT문 1),
[별칭2] AS (SELECT문 2),
...,
[별칭N] AS (SELECT문 N)
SELECT
FROM 별칭1, 별칭2, ..., 별칭N
WITH E AS (SELECT * FROM EMP WHERE DEPTNO = 10),
D AS (SELECT * FROM DEPT)
SELECT E.EMPNO, E.ENAME, E.DEPTNO, D.DNAME, D.LOC
FROM E, D
WHERE E.DEPTNO = D.DEPTNO;
SELECT절 서브쿼리
= 스칼라 서브쿼리
SELECT절 서브쿼리는 반드시 하나의 결과만을 반환해야 함
SELECT EMPNO,
ENAME,
JOB,
SAL,
(SELECT GRADE FROM SALGRADE WHERE E.SAL BETWEEN LOSAL AND HISAL) AS SALGRADE,
DEPTNO,
(SELECT DNAME FROM DEPT WHERE E.DEPTNO = DEPT.DEPTNO) AS DNAME
FROM EMP E;
728x90
반응형
'Programming > Database' 카테고리의 다른 글
[ORACLE 초급] 트랜잭션(COMMIT, ROLLBACK), SESSION, LOCK (0) | 2020.09.26 |
---|---|
[ORACLE 초급] DML - INSERT, UPDATE, DELETE (feat. 서브쿼리) (0) | 2020.09.26 |
[ORACLE 초급] 문법별 JOIN 사용법 - 내부조인, 외부조인, JOIN ~ USING/ON (0) | 2020.09.20 |
[ORACLE 중급] 그룹화 함수 - ROLLUP, CUBE, GROUPING, PIVOT 등 (0) | 2020.09.18 |
[ORACLE 초급] 데이터 그룹화 GROUP BY절, HAVING절 (0) | 2020.09.18 |