# SET operator
UNION / UNION ALL : 차이는 중복 결과 1번 출력 / 모두 출력
INTERSECT : 양쪽 쿼리 결과에 모두 포함되는 행만 표현
MINUS : 쿼리 결과 1에는 포함되지만 쿼리 결과 2에는 포함되지 않는 결과만
-- 기본적인 SET
SELECT DEPT_ID
FROM EMPLOYEE
UNION
SELECT DEPT_ID
FROM DEPARTMENT;
-- 더미 데이터 NULL 활용하기
SELECT EMP_NAME
, JOB_ID
, DEPT_ID
FROM EMPLOYEE
UNION
SELECT NULL
, NULL
, DEPT_ID
FROM DEPARTMENT
-- 특정 값 넣기
SELECT EMP_ID
, EMP_NAME
, '관리자' AS 구분
FROM EMPLOYEE
WHERE EMP_ID = '141'
AND DEPT_ID = '50';
UNION
SELECT EMP_ID
, EMP_NAME
, '직원' AS 구분
FROM EMPLOYEE
WHERE DEPT_ID = '50'
AND EMP_ID != '141';
ORDER BY 3, 1;
반드시 UNION을 안쓰더라도 IN 을 통해 같은 효과를 낼 수 있는 경우도 있다!
-- IN 활용
SELECT EMP_NAME
, JOB_TITLE 직급
FROM EMPLOYEE
JOIN JOB USING (JOB_ID)
WHERE JOB_TITLE IN ('대리', '사원')
ORDER BY 2,1
-- UNION 활용
SELECT EMP_NAME, '사원' 직급
FROM EMPLOYEE
JOIN JOB USING (JOB_ID)
WHERE JOB_TITLE = '대리'
UNION
SELECT EMP_NAME , '대리' 직급
FROM EMPLOYEE
JOIN JOB USING (JOB_ID)
WHERE JOB_TITLE = '대리'
ORDER BY 2,1;
# SubQuery
하나의 쿼리가 다른 쿼리에 포함되는 구조
다른 쿼리에 포함된 내부 쿼리(서브 쿼리)는 외부 쿼리(메인 쿼리)에 사용될 값을 반환하는 역할
# 단일 행 서브 쿼리
단일 행 반환 / 단일 행 비교 연산자 사용
# 다중 행 서브 쿼리
여러 행 반환 / 다중 행 비교 연산자 사용
SELECT EMP_NAME
, JOB_ID
, SALARY
FROM EMPLOYEE
WHERE JOB_ID = (SELECT JOB_ID
FROM EMPLOYEE
WHERE EMP_NAME = '나승원')
AND SALARY > (SELECT SALARY
FROM EMPLOYEE
WHERE EMP_NAME = '나승원');
-- SUB QUERY
SELECT EMP_NAME
, JOB_ID
, SALARY
FROM EMPLOYEE
WHERE SALARY = (SELECT MIN(SALARY)
FROM EMPLOYEE);
-- Sub Query
SELECT DEPT_NAME
, SUM(SALARY)
FROM EMPLOYEE
LEFT JOIN DEPARTMENT USING(DEPT_ID)
GROUP BY DEPT_ID, DEPT_NAME
HAVING SUM(SALARY) = (SELECT MAX(SUM(SALARY))
FROM EMPLOYEE
GROUP BY DEPT_ID);
-- 부서마다 최소 연봉과 동일한 연봉 지닌 사람들
SELECT EMP_ID
, EMP_NAME
FROM EMPLOYEE
WHERE SALARY IN (SELECT MIN(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_ID);
-- 부서마다 최소 연봉 찾기
SELECT EMP_ID
, EMP_NAME
FROM EMPLOYEE
WHERE (SALARY, DEPT_ID) IN (SELECT MIN(SALARY), DEPT_ID
FROM EMPLOYEE
GROUP BY DEPT_ID)
SUB QUERY를 먼저 구성하고 결과를 살펴본 다음에 어떻게 맵핑 또는 비교를 할지를 판단하기
섣부르게 MAIN QUERY 먼저 접근하지 않기
CF. SUB QUERY에 대해 NOT IN을 쓸 거면 NULL 값이 있는지 없는지 고려하기
-- SUB QUERY
SELECT EMP_ID
, EMP_NAME
, '관리자' AS 구분
FROM EMPLOYEE
WHERE EMP_ID IN (SELECT MGR_ID FROM EMPLOYEE)
UNION
SELECT EMP_ID
, EMP_NAME
, '직원'
FROM EMPLOYEE
WHERE EMP_ID NOT IN(SELECT MGR_ID FROM EMPLOYEE
WHERE MGR_ID IS NOT NULL)
ORDER BY 3, 1;
IN / ANY 는 범위 조회에 많이 활용됨
< ANY : 비교 대상 중 최대 값 보다 작음
> ANY : 비교 대상 중 최소 값 보다 큼
ANY를 사용하게 되면 어떤 하나라도 가능(박스 안에서 비교하는 것)
-- ANY 어떤 한 과장 직급보다 많이 받는 대리 들
SELECT EMP_NAME
, SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE = '대리'
AND SALARY > ANY(SELECT SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE = '과장')
CF. FROM 절에 사용하면 INLINE VIEW / SELECT에 쓰면 SCALAR QUERY
INLINE VIEW 활용
-- 직급별 평균급여 조회
-- 에 해당하는 직원 정보 조회
SELECT E.EMP_NAME
, J.JOB_TITLE
, E.SALARY
FROM (SELECT JOB_ID
, TRUNC(AVG(SALARY), -5) JOBAVG
FROM EMPLOYEE
GROUP BY JOB_ID) V
JOIN EMPLOYEE E ON(E.SALARY = V.JOBAVG AND E.JOB_ID = V.JOB_ID)
JOIN JOB J ON(J.JOB_ID = E.JOB_ID)
# EXISTS, NOT EXISTS 둘 다 사용 가능
CF. SUB QUERY는 DB 성능에 치명적인 부분이므로 최대한으로 어떻게 처리할 지 고민해보기!
상황마다 일반 서브 쿼리, INLINE VIEW, SCALAR SUB QUERY 성능 고려해보기
'Archived(CSE Programming) > SQL(Oracle)' 카테고리의 다른 글
SQL_DML (0) | 2020.01.29 |
---|---|
SQL_DDL (0) | 2020.01.23 |
SQL_JOIN (0) | 2020.01.21 |
SQL_Additional_SELECT_그룹 함수 (0) | 2020.01.21 |
SQL_Additional_SELECT_단일 행 함수 (0) | 2020.01.20 |