본문 바로가기

Database

[SQL] 서브쿼리 (SUBQUERY)

서브쿼리

- 하나의 쿼리 문장 내에 또 다른 쿼리문이 들어있는 것
- 하나의 SQL문안에 포함된 또 하나의 QUERY문
- 메인 SQL문을 보조해주는 QUERY문



서브쿼리 사용시 주의사항

- 비교연산자의 오른쪽에 기술해야 하고 반드시 괄호 안에 넣어야 함.
- 메인 쿼리가 실행되기 이전에 한 번만 실행됨.
- 서브쿼리를 괄호로 감싸서 사용한다.
- 서브쿼리는 단일 행 또는 복수 행 비교 연산자와 함께 사용 가능하다.
- 서브쿼리에서는 ORDER BY 를 사용하지 못한다.


서브쿼리가 사용 가능한 곳

1. SELECT 절
2. FROM 절
3. WHERE 절
4. HAVING 절
5. ORDER BY 절
6. INSERT 문의 VALUES 절
7. UPDATE 문의 SET 절

SELECT절
서브쿼리

(스칼라 서브쿼리)
SELECT절에 서브쿼리 제시

서브쿼리의 결과는 반드시 단일행 OR 집계함수 결과값(단일값 : SUM, COUNT 등) 리턴
-> 서브쿼리의 결과값이 메인쿼리에서 속성으로 SELECT되어야 하기 때문
FROM절 서브쿼리
(Inline View)
FROM 절에 서브쿼리를 제시
서브쿼리를 수행한 결과(RESULT SET)을 테이블로 사용
이 때, 서브쿼리의 결과는 반드시 하나의 테이블로 리턴되어야 함



주로 사용하는 예:
TOP N 분석: 데이터베이스 상에 존재하는 자료 중 최상위 몇개 자료를 보기 위해 사용
ROWNUM: 오라클에서 제공해주는 컬럼, 조회된 순서대로 1부터...순번 부여해줌

*/


중첩 서브쿼리
( Nested Subqueries )
WHERE 절 안에 서브쿼리가 들어있음
가장 자주 쓰이는 대중적인 서브쿼리이며 단일행과 복수행 둘 다 리턴 가능
단일행[단일열]
서브쿼리
- 서브쿼리의 수행결과가 오직 하나의 행과 열만을 반환
- 이 하나의 결과를 가지고 메인쿼리는 비교연산자를 통해 쿼리를 수행함.
- 비교연산자는 단일행 비교연산자를 사용 ( >, >=, <, <=, =, ... )
다중행서브쿼리 서브쿼리의 수행결과가 두 건 이상의 데이터를 반환.
- 비교연산자는다중행 비교연산자를 사용 ( IN, ANY, SOME, ALL, EXISTS ).
==> 서브쿼리를 수행한 결과가 몇행 몇열이냐에 따라 사용가능한 연산자가 달라짐

IN /NOT IN:메인쿼리의 비교조건이 서브쿼리의 결과중에서 하나라도 일치하면 결과 반환
ALL
메인쿼리의 비교조건이 서브쿼리의 검색결과와 모든 값이 일치하면
- 메인쿼리 < ALL ( 서브쿼리 ) : 서브쿼리의 결과와 비교해 메인쿼리의 데이터 전부가 서브쿼리 결과보다 작다면 최소값 반환
- 메인쿼리 > ALL ( 서브쿼리 ) : 서브쿼리의 결과와 비교하여 최대값 반환

ANY
메인쿼리의 비교조건이 서브쿼리의 검색결과와 하나 이상이 일치하면 결과반환
- 메인쿼리 < ANY ( 서브쿼리 ) : 서브쿼리의 결과와 비교해 메인쿼리의 데이터중 한개라도 서브쿼리 결과보다 작다면 최소값 반환
- 메인쿼리 > ANY ( 서브쿼리 ) : 서브쿼리의 결과와 비교해 메인쿼리의 데이터중 한개라도 서브쿼리 결과보다 크다면 최대값 반환

EXISTS
메인쿼리의 비교조건이 서브쿼리의 검색결과중에 하나라도 만족하는 값이 존재하면 결과반환
EXISTS 는 해당 로우가 존재하는지의 여부만 확인
IN은 실제 존재하는 데이터들의 모든 값까지 확인
NOT EXISTS는 메인쿼리의 컬럼명과 서브쿼리의 컬럼명을 비교하여 일치하지 않으면 메인쿼리 테이블의 모든 ROW(행)을 반환
2) [단일열] 다중행 서브쿼리: 서브쿼리를 수행한 결과값이 여러행일때

- IN : 여러개의 결과값(행) 중에서 하나라도 일치하는 값이 있으면
- NOT IN : 아예 없으면

3) [단일행] 다중열 서브쿼리 : 서브쿼리를 수행한 결과값이 여러 열일 때
조회 결과값은 한 행이지만 나열된 컬럼수가 여러개일 때
4) 다중행 다중열 서브쿼리 :
서브쿼리 조회 결과값이 여러행, 여러 컬럼일 경우

참고:
https://mjn5027.tistory.com/51#%EB%8B%A8%EC%9D%BC%ED%96%89%20%EC%84%9C%EB%B8%8C%EC%BF%BC%EB%A6%AC

- 다중행
SELECT EMP_NAME, DEPT_CODE, JOB_CODE, HIRE_DATE
FROM EMPLOYEE
WHERE  DEPT_CODE =  (SELECT DEPT_CODE
FROM EMPLOYEE
WHERE EMP_NAME = '하이유')
AND JOB_CODE = (SELECT  JOB_CODE
FROM EMPLOYEE
WHERE EMP_NAME = '하이유');


-- 다중열 서브쿼리
SELECT EMP_NAME, DEPT_CODE, JOB_CODE, HIRE_DATE
FROM EMPLOYEE
WHERE  (DEPT_CODE, JOB_CODE) =  (SELECT DEPT_CODE, JOB_CODE
FROM EMPLOYEE
WHERE EMP_NAME = '하이유');



--- 다중행
SELECT EMP_ID, EMP_NAME, JOB_CODE, SALARY
FROM EMPLOYEE
WHERE  ( JOB_CODE, SALARY ) IN (SELECT JOB_CODE, MIN(SALARY)   
                                                    FROM EMPLOYEE
                                                    GROUP BY JOB_CODE);
                                                    
                                                    
                                                    -- 인라인뷰

SELECT *
FROM (SELECT EMP_ID, EMP_NAME, (SALARY+SALARY*NVL (BONUS, 0))*12 "보너스연봉", DEPT_CODE
                FROM EMPLOYEE )
WHERE "보너스연봉" > 30000000;

SELECT ROWNUM, EMP_NAME, SALARY
FROM  (SELECT* 
FROM EMPLOYEE
ORDER BY SALARY DESC)
WHERE ROWNUM <=5;

'Database' 카테고리의 다른 글

[SQL] DML - INSERT/ UPDATE /DELETE  (0) 2022.10.04
[SQL] 제약조건 (CONSTRAINTS)  (0) 2022.10.04
[SQL] 집합연산자 (SET OPERATOR)  (0) 2022.10.04
[SQL] 조인 (JOIN)  (1) 2022.10.04
[SQL] 함수 - 그룹함수  (0) 2022.10.04