Notice
Recent Posts
Recent Comments
Link
나의 개발일지
[SQL] 서브 쿼리 본문
서브 쿼리와 메인 쿼리
- 메인 쿼리 (외부 쿼리)
- 결과를 반환할 때 사용할 최종 쿼리문
- 서브 쿼리 (내부 쿼리)
- SQL 문 내부에 포함되는 괄호 안의 쿼리문
- 중첩 SELECT 문 또는 하위 SELECT 문
- 외부 쿼리 (메인 쿼리)에 사용될 값만 처리
- 서브 쿼리 결과는 화면에 반환되지 않음
- 특별한 경우를 제외하고는 서브 쿼리는 메인 쿼리보다 먼저, 한 번만 실행
서브 쿼리가 필요한 경우
- 두 개의 순차적인 쿼리를 수행하여 첫 번째 쿼리 결과를 두 번째 쿼리의 검색 값으로 사용하는 경우와 동일한 작업을 하나의 SQL에서 실행
- 예시) 오상우 사원보다 급여가 많은 사원을 구하기 위해 먼저 오상우 사원의 급여를 구한다. (630)
- 그다음 오상우 사원의 급여인 630을 가지고 조건을 검색하는 쿼리를 또 작성한다. 이렇게 총 두 번의 쿼리 실행
- 두 번 해야하는 쿼리를 서브 쿼리를 사용해 한 번에 끝낼 수 있다.
서브 쿼리의 실행
- 조건 값을 알 수 없는 SQL 문을 작성하는데 매우 유용
- 주로 WHERE과 HAVING 절에서 연산자의 오른쪽에 많이 사용
- SQL 문장에서 서브쿼리가 사용될 수 있는 경우
- WHERE 절
- HAVING 절
- FROM 절
- OREDR BY 절
서브 쿼리의 구문
- 서브 쿼리는 괄호로 묶어야 하며 일반적으로 비교조건의 오른쪽에 위치
- 한 개의 메인 쿼리에 여러 개의 서브 쿼리가 존재 가능
- 구문
SELCET select_list
FROM table
WHERE 표현식 연산자 (SELECT select_list
FROM table);
- 오상우 사원보다 급여를 많이 받는 직원의 이름과 직위, 급여를 표시
- WHERE 조건은 salary > 630과 같은 의미가 된다.
SELECT emp_name, position, salary
FROM y_emp
WHERE salary > (SELECT salary FROM y_emp
WHERE emp_name = '오상우');
서브 쿼리의 종류
- 반환되는 행의 수 기준
- 단일 행 서브 쿼리
- 다중 행 서브 쿼리
- 다중 열 서브 쿼리
- 인라인 뷰
- FROM 절에 사용된 서브 쿼리
- 스칼라 서브 쿼리
- 하나의 단일 값을 나타내기 위해 SELECT LIST, WHERE 절, ORDER BY 절, DML 등에 사용하는 서브 쿼리
- 상호 관련 서브 쿼리
- 메인 쿼리와 서브 쿼리의 특정 열 값을 상호비교
단일 행 서브 쿼리와 다중 행 서브 쿼리
- 서브 쿼리에서 반환되는 행 수에 의해 구분
- 서브 쿼리로부터 단일 행을 반환 : 단일 행 서브 쿼리
- 서브 쿼리로부터 여러 행을 반환 : 다중 행 서브 쿼리
- 서브 쿼리에서 사용될 비교 연산자를 구분하여 사용
- 단일 행 연산자 (>, =, >=, <, <>, <=)
- 여러 행 연산자 (IN, ANY, ALL)
단일 행 서브 쿼리
- 내부 SELECT 문 (서브 쿼리) 에서 하나의 행을 반환하는 서브 쿼리
- 단일 행 비교 연산자를 이용
- 사용 가능한 단일 행 비교 연산자
- =, >, >=, <, <=, <>
- 1049번 사원과 직급이 동일한 사원을 표시
- WHERE position = '과장' 과 같은 의미
SELECT emp_name, position
FROM y_emp
WHERE position = (SELECT position FROM y_emp
WHERE emp_id = 1049);
- 1044번 사원과 업무가 동일하면서 1050번 사원보다 급여를 많이 받는 사원을 반환하기 위한 구문
SELECT emp_name, position, salary FROM y_emp
WHERE position = (SELECT position FROM y_emp
WHERE emp_id = 1044)
AND salary > (SELECT salary FROM y_emp
WHERE emp_id = 1050);
- 서브 쿼리의 MIN 그룹 함수를 사용하여 회사에서 가장 적은 급여를 받는 사원에 대한 정보가 출력
SELECT emp_id, emp_name, position, salary
FROM y_emp
WHERE salary = (SELECT MIN(salary)
FROM y_emp);
- HAVING 절에 서브 쿼리를 사용하여 회사의 업무 중 평균 급여가 가장 낮은 직급과 그 평균 급여를 반환
SELECT position, AVG(salary)
FROM y_emp
GROUP BY position
HAVING AVG(salary) = (SELECT MIN(AVG(salary)) FROM y_emp
GROUP BY position);
서브 쿼리에서 발생할 수 있는 문제
- 연산자의 잘못된 사용
- 단일 행 비교 연산자를 사용하면서 서브 쿼리에서는 여러 행을 반환하는 경우
- 쿼리의 구조를 변경하거나 연산자의 종류 변경
- 내부 쿼리에서 행을 반환하지 않는 경우
- 이 경우 서브 쿼리는 NULL 값을 반환하고 메인 쿼리는 서브 쿼리의 결과(NULL)를 받아 WHERE 절에서 사용
- 결과로 아무 행이 반환되지 않음
- 잘못 작성된 서브 쿼리 사용자가 잘못된 데이터를 최종 결과로 사용
- 오류 예시) 직급이 차장인 사원과 급여가 같은 사원을 찾는 문장에서 서브 쿼리가 여러 행을 반환해 다일행 서브쿼리인 메인 쿼리가 오류를 반환
SELECT emp_id, emp_name, position, salary
FROM y_emp
WHERE salary = (SELECT salary FROM y_emp
WHERE position = '차장');
다중 행 서브 쿼리
- 여러 행을 반환하는 서브 쿼리
- 여러 값을 처리하는 다중 행 연산자를 사용
- 다중 행 연산자의 종류
- IN : 목록의 임의의 값과 동등 비교
- ANY : 값을 서브 쿼리에 의해 반환된 각 값과 비교
- ALL : 값을 서브 쿼리에 의해 반환된 모든 값과 비교
- 200번 이하의 부서에 대하여 각 부서의 최고 급여를 구한 후 그 급여와 동일한 급여를 받는 사원정보를 반환
SELECT emp_name, salary, dept_id
FROM y_emp
WHERE salary IN (SELECT MAX(salary)
FROM y_emp
WHERE dept_id <= 200
GROUP BY dept_id);
- 직책이 대리가 아니면서 급여가 임의의 대리인 사원보다 낮은 사원을 표시
- 대리 급여의 최댓값인 570보다 낮으면 모두 나옴 (모든 대리들의 급여들 보다 낮기만 하면 되기 때문에)
SELECT emp_id, emp_name, position, salary
FROM y_emp
WHERE salary < ANY
(SELECT salary FROM y_emp
WHERE position = '대리')
AND position <> '대리';
- 직책이 대리가 아니면서 급여가 임의의 대리인 사원보다 높은 사원을 표시
- 대리 급여의 최솟값인 350보다 높으면 모두 나옴 (모든 대리들의 급여들 보다 높기만 하면 되기 때문에)
SELECT emp_id, emp_name, position, salary
FROM y_emp
WHERE salary > ANY
(SELECT salary FROM y_emp
WHERE position = '대리')
AND position <> '대리';
- 직책이 대리가 아니면서 급여가 대리 중 가장 낮은 사람 보다 낮은 사원을 표시
- 대리 급여의 최솟값인 350보다 낮으면 모두 나옴 (모든 대리들의 급여들과 비교해서 낮아야 하기 때문에)
SELECT emp_id, emp_name, position, salary
FROM y_emp
WHERE salary < ALL
(SELECT salary FROM y_emp
WHERE position = '대리')
AND position <> '대리';
다중 열 서브 쿼리
To Be Continue..
'Oracle SQL' 카테고리의 다른 글
[SQL] 데이터베이스 트랜잭션 (0) | 2023.05.30 |
---|---|
[SQL] 데이터 조작어 (DML) (0) | 2023.05.02 |
[SQL] JOIN (0) | 2023.04.18 |
[SQL] GROUP BY 절의 추가 기능 (ROLLUP, CUBE, GROUPING SETS) (0) | 2023.04.16 |
[SQL] GROUP BY, 그룹 결과 정렬, HAVING 절 (0) | 2023.04.16 |
Comments