본문 바로가기

dev/DB

서브쿼리

subquery

  • 메인 쿼리 내부에 사용되는 SELECT 문을 말한다.
  • 인라인 뷰, 스칼라 서브쿼리, 서브쿼리로 나눌 수 있다.
  • 인라인 뷰 : FROM 절에서 뷰처럼 사용되는 SELECT 문이다. FROM절에 임시 테이블 공간을 생성하며, 뷰와 비슷한 형태다.
  • 스칼라 서브쿼리 : SELECT 절에서 함수처럼 사용되는 SELECT 문이다. 반환값은 한개여야 한다(함수이므로)
  • 서브쿼리 : WHERE 절에서 조건으로 사용되는 SELECT 문이다.
[tip] 서브 쿼리를 이용할 때는 반드시 괄호()를 쓴다!

1. 인라인 뷰

  • FROM 절에 테이블이 바로 오는 것이 아니라, SELECT 절이 오는 방식
  • SELECT 로 추출된 뷰가 FROM절에 오는 것으로 볼 수 있다.
  • MSSQL에서는 인라인 뷰를 사용할 때 인라인 뷰에 대한 앨리어스를 사용해 주어야 한다.

SELECT * 

FROM (SELECT ROWNUM NUM, ENAME FROM EMP) a

WHERE NUM < 5; // a 뷰에서 NUM 컬럼이 <5인것을 조회한다.



2. 스칼라 서브쿼리

  • 반드시 하나의 행과 하나의 컬럼만 반환한다.
  • 조회 결과에 계산된 값 컬럼을 추가할 때 주로 사용한다.
// 스칼라 서브쿼리를 이용해 직원의 평균 급여를 계산하는 예시
SELECT ENAME AS "이름" ,
SAL AS "급여", 
(SELECT AVG(SAL) FROM EMP) AS "평균급여" // 하나의 행만 조회 되어야 한다.
FROM EMP
WHERE EMPNO=1000;


3. 서브쿼리

  • WHERE절에서 조건으로 사용되는 서브쿼리이다.
  • 서브쿼리가 반환하는 행의 수에 따라 단일 행 서브쿼리다중 행 서브쿼리로 분류된다.
  • 단일 행 서브쿼리 : 하나의 행만 반환한다. 비교 연산자(=,<,<= 등등)를 사용한다.
  • 다중 행 서브쿼리 : 여러 행을 반환한다. IN, ANY, ALL, EXISTS를 사용한다.

3-1. 단일 행 서브쿼리

  • 하나의 행만 반환한다. 
  • 하나의 행이 반환되므로 비교 연산자(=,<,<= 등등)를 사용해 조건으로 사용 가능하다.

SELECT * FROM EMP

WHERE DEPTNO =                // 서브쿼리 결과가 하나의 행(값)으로 반환도므로 비교 연산자를 통해 조건으로 사용 가능하다.

(SELECT DEPTNO FROM DEPT

WHERE DEPTNO=10); 


// 서브쿼리는 다음 결과를 반환한다.

DEPTNO 

 10

//따라서 메인쿼리의 WHERE 절 조건은 DEPTNO = 10과 같은 결과가 나온다.

ENPNO 

DEPTNO 

ENAME 

1006 

10 

tester01 

1012 

10 

tester02 



3-2. 다중 행 서브쿼리

  • 서브쿼리 결과가 여러 행으로 나온다.
  • 따라서 서브쿼리 결과에 대해 IN,ALL,ANY,EXISTS를 이용해야 한다. (WHERE절의 서브쿼리는 조건을 위해 사용하므로)

연산 

설명 

ALL 

조건을 모두 만족하는 데이터를 조회 (=and)

ANY 

조건을 하나라도 만족하는 데이터를 조회  (=or) 

(NOT) IN 

서브쿼리의 결과 값과 같은 값을 갖는 데이터를 조회

 (NOT) EXISTS

하나라도 존재하면 true


1) ALL 예시
SELECT * FROM EMP T1
WHERE T1.SALARY > ALL(SELECT S1.SALARY
FROM EMP S1
LEFT JOIN DEPT S2 ON (S2.DEPT_CD = S1.DEPT_CD)
WHERE S2.DEPT_NAME = "마케팅부서") // 서브쿼리 결과로 1800만원, 2200만원, 3000만원이 조회된다고 가정
 // 서브쿼리 결과를 전부 일치하는 데이터만 조회되므로 T1.SALARY > (1800 AND 2200 AND 3000)을 조회하게 됨.


2) ANY 예시

SELECT * FROM EMP T1
WHERE T1.SALARY > ANY(SELECT S1.SALARY
FROM EMP S1
LEFT JOIN DEPT S2 ON (S2.DEPT_CD = S1.DEPT_CD)
WHERE S2.DEPT_NAME = "마케팅부서") // 서브쿼리 결과로 1800만원, 2200만원, 3000만원이 조회된다고 가정
 // 서브쿼리 결과 중 하나라도 일치하는 데이터를 조회하므로 T1.SALARY > (1800 OR 2200 OR 3000)을 조회하게 됨.

3) IN 예시

* 알맞는 select 문은 아니지만 위의 쿼리를 이용해 예시 작성

SELECT * FROM EMP T1
WHERE T1.SALARY  IN(SELECT S1.SALARY
FROM EMP S1
LEFT JOIN DEPT S2 ON (S2.DEPT_CD = S1.DEPT_CD)
WHERE S2.DEPT_NAME = "마케팅부서") // 서브쿼리 결과로 1800만원, 2200만원, 3000만원이 조회된다고 가정
 // 서브쿼리 결과 중 하나라도 일치하는 데이터를 조회하므로 T1.SALARY 값이 (1800, 2200, 3000)에 해당하는 데이터를 조회하게 됨.


4) EXISTS 예시

SELECT ENAME, DNAME, SAL

FROM EMP, DEPT

WHERE EMP.DEPTNO = DEPT.DEPTNO

AND EXISTS (SELECT 1 FROM EMP

WHERE SAL > 2000) // 급여(SAL)이 2000이상인 사원이 있으면 TRUE가 된다.


4. Correlated subquery

  • subquery 내에서 main query의 칼럼을 사용하는 것을 말함
SELECT * FROM EMP a
WHERE a.DEPTNO =
(SELECT DEPTNO FROM DEPT b 
WHERE b.DEPTNO=a.DEPTNO);


[참조]

subquery 사용법 : https://aljjabaegi.tistory.com/14

SQL 개발자 이론서+문제집, 임호진, 영진닷컴

'dev > DB' 카테고리의 다른 글

window 함수  (0) 2019.03.10
그룹 함수  (0) 2019.03.10
SQL 표준 함수  (0) 2019.03.10
Join  (0) 2019.03.07
Java 진영의 persistent framework  (0) 2019.03.07