메인 쿼리가 서브쿼리를 포함하는 종속적인 관계
조건
- 서브쿼리는 반드시 소괄호로 묶어야 한다. (SELECT ... FROM ... WHERE ... )
- 서브쿼리는 연산자의 오른쪽에 위치 해야 한다.
- WHERE 구문에서 사용되는 서브쿼리 내에서 order by 문법은 지원 하지 않는다.
서브쿼리의 조회 결과 값(행, 열)의 개수 1개
EX)
SELECT DEPT_CODE AS "부서번호",
EMP_ID AS "사원번호",
EMP_NAME AS "사원명",
SALARY AS "급여"
FROM EMPLOYEE
WHERE DEPT_CODE IN ('D1', 'D2') AND SALARY > (SELECT AVG(SALARY)
FROM EMPLOYEE
WHERE DEPT_CODE='D5');
- IN
- 쿼리의 비교 조건이 쿼리 결과 중에서 하나라도 일치하는 것 (OR)
- NOT IN
- 쿼리의 비교 조건 결과 중에서 하나라도 일치하지 않는 것
- ANY
- 서브 쿼리의 결과 중에서 하나라도 참이면 참 (범위를 표현하는 OR 개념)
구분 의미 > ANY 최소값보다 크면 >= ANY 최소값보다 크거나 같으면 < ANY 최대값보다 작으면 <= ANY 최대값보다 작거나 같으면 = ANY IN과 같은 효과 != ANY NOT IN과 같은 효과
- ALL
- 서브 쿼리의 결과 중 모두 참이면 참 (ALL은 AND 개념)
구분 의미 > ALL 최대값보다 크면 >= ALL 최대값보다 크거나 같으면 < ALL 최소값보다 작으면 <= ALL 최소값보다 작거나 같으면 = ALL 결과가 1개면 같은! 여러개면 오류 발생 != ALL 결과가 1개면 같지 않은! 여러개면 오류 발생
- EXISTS
- 데이터가 있는지 없는지를 비교하기 위한 연산자
- 데이터가 있으면 참, 없으면 거짓
- Table의 양이 많은 경우 모두 찾기 보다 있는지 없는지 여부를 먼저 파악
SELECT JOB_NAME AS "직급명" , EMP_NAME AS "사원명"
FROM EMPLOYEE
LEFT JOIN JOB USING (JOB_CODE)
WHERE SAL_LEVEL IN (SELECT SAL_LEVEL
FROM EMPLOYEE
WHERE EMP_NAME IN ('차태연','전지연'))
AND EMP_NAME NOT IN ('차태연','전지연');
SELECT EMP_NAME, DEPT_TITLE, JOB_CODE
FROM EMPLOYEE
LEFT JOIN DEPARTMENT ON(DEPT_CODE=DEPT_ID)
WHERE JOB_CODE NOT IN (SELECT JOB_CODE
FROM JOB
WHERE JOB_NAME IN ('대표', '부사장'));
SELECT EMP_NAME, SALARY, DEPT_CODE
FROM EMPLOYEE
WHERE SALARY < ANY ( SELECT SALARY
FROM EMPLOYEE
WHERE DEPT_CODE IN ('D1','D5') );
SELECT EMP_NAME, SALARY, DEPT_TITLE
FROM EMPLOYEE
LEFT JOIN DEPARTMENT ON (DEPT_CODE=DEPT_ID)
WHERE SALARY <= ALL (SELECT AVG(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE);
SELECT *
FROM EMPLOYEE
WHERE EXISTS(SELECT 1 FROM EMPLOYEE WHERE SALARY>8000000) ;
SELECT EMP_ID AS "사번", EMP_NAME AS "이름", DEPT_TITLE AS "부서명", JOB_NAME AS "직책명"
FROM EMPLOYEE
LEFT JOIN DEPARTMENT ON(DEPT_CODE=DEPT_ID)
LEFT JOIN JOB USING (JOB_CODE)
WHERE (DEPT_CODE, JOB_CODE)IN (SELECT DEPT_CODE, JOB_CODE
FROM EMPLOYEE
WHERE EMP_ID = 205);
SELECT EMP_NAME, EMP_ID, DEPT_CODE, HIRE_DATE, SALARY *12
FROM EMPLOYEE
WHERE (JOB_CODE , SALARY) IN ( SELECT JOB_CODE , MIN(SALARY)
FROM EMPLOYEE
GROUP BY JOB_CODE);
FROM 절에서 서브쿼리를 사용하는 것
TOP-N 분석시 자주 활용 됨
EX) 사용법 예시
SELECT ROWNUM, EMP_NAME, "보너스 금액" -- BONUS*SALARY 쓴다고 같은거 아님, 별칭 사용해야함
FROM(
SELECT EMP_NAME, (SALARY*BONUS) AS "보너스 금액"
FROM EMPLOYEE
WHERE BONUS IS NOT NULL
ORDER BY "보너스 금액" DESC) -- BONUS*SALARY 쓴다고 같은거 아님, 별칭 사용해야함
WHERE ROWNUM<=2;
SELECT *
FROM(
SELECT ROWNUM AS "RN", EMP_NAME, "보너스 금액" -- ROWNUM 별칭 적용
FROM(
SELECT EMP_NAME, (SALARY*BONUS) AS "보너스 금액"
FROM EMPLOYEE
WHERE BONUS IS NOT NULL
ORDER BY "보너스 금액" DESC))
WHERE "RN" BETWEEN 3 AND 5; -- ROWNUM 별칭으로 조건 설정
WITH NEW_DATA AS (SELECT ROWNUM AS "RN", EMP_NAME, "보너스 금액"
FROM(
SELECT EMP_NAME, (SALARY*BONUS) AS "보너스 금액"
FROM EMPLOYEE
WHERE BONUS IS NOT NULL
ORDER BY "보너스 금액" DESC))
SELECT *
FROM NEW_DATA
WHERE "RN" BETWEEN 3 AND 5;
구분 | 의미 |
---|---|
RANK() OVER | 중복되는 순위는 동일 순위로 출력하고, 다음 순위는 그만큼 건너뛰고 반환 ex) 1,2,3,4,5,6,6,6,9,10 |
DENSE_RANK() OVER | 중복되는 순위는 동일 순위로 출력하고, 다음 순위 순차적으로 반환 ex) 1,2,3,4,5,6,6,6,7,8,9,10 |
ROW_NUMBER() OVER | 중복과 관계 없이 무조건 순서대로 반환 /동일 값이라면 출력되는 순서가 우선순위로 표기 ex) 1,2,3,4,5,6,7,8,9,10 |
SELECT *
FROM(
SELECT
RANK() OVER(ORDER BY SALARY DESC) AS "RANK",
DENSE_RANK() OVER(ORDER BY SALARY DESC) AS "DENSE_RANK",
ROW_NUMBER() OVER (ORDER BY SALARY DESC) AS "ROW_NUMBER",
EMP_NAME, SALARY
FROM EMPLOYEE);