Sub Query
- 서브쿼리는 SQL 문 안에 포함된 또 다른 SQL 문을 의미
- SELECT 문 안에 다시 SELECT 문이 기술된 형태의 쿼리
- 서브 쿼리의 용도는 알려지지 않은 기준을 위한 검색을 위해 사용
- 메인쿼리와 서브쿼리 관계는 주종 관계로서, 서브쿼리에 사용되는 컬럼 정보는 메인쿼리의 컬럼 정보를
사용할 수 있으나 역으로는 성립하지 않는다.
- 상위 SELECT 문 안에 하위 SELECT 문이 포함된 형태라 중첩된(nested) 쿼리라고도 부름
- 단일 SELECT 문 사용만으로는 복잡한 조건식을 만들 때 사용
- 다른 테이블에서 데이터 값을 조회한 후 조건으로 사용할 때 사용
> 서브 쿼리 종류 (데이터 형태 기준)
- 단일 행 서브 쿼리(Single Row) - 중첩 서브쿼리(Nested SubQuery)
: 하나의 행을 검색하는 서브 질의 / 결과가 항상 1건 이하인 서브쿼리
: 단일 행 비교 연산자 <, >, = 가 사용 - 다중 행 서브 쿼리(Multiple Row) - 중첩 서브쿼리(Nested SubQuery)
: 하나 이상의 행을 검색하는 서브 질의 / 실행 결과가 여러 건인 서브 쿼리
: 다중 행 비교 연산자 사용 IN, ALL, ANY, EXIST 가 사용 - 다중 열 서브 쿼리(Multiple Column)
: 하나 이상의 열을 검색하는 서브 질의 / 결과가 여러 컬럼으로 반환되는 서브 쿼리
: 메인 쿼리의 조건절에 여러 컬럼을 동시에 비교할 때, 서브 쿼리와 메인 쿼리에서 비교하는 컬럼 개수와 위치가 동일
> 서브 쿼리 종류 (위치 기준)
- FROM 절 서브쿼리
- 서브 쿼리가 FROM 절 안에 들어있는 형태
- 인라인 뷰(Inline Views)라고 불림
- 뷰(View)처럼 결과가 동적으로 생성된 테이블 형태로 사용할 수 있음 - WHERE 절 서브쿼리
- 서브쿼리가 WHERE 절 안에 들어 있는 형태
- 중첩 (Nested Sub-Query) 라고도 불림
Detail
- 단일 행 서브 쿼리
- : 서브쿼리 SELECT 문에서 단일 행 결과를 메인 쿼리에 전달
- : WHERE 절에 사용되는 열의 개수와 데이터 타입 일치 필요
- : 단일 행 연산자 사용: >, <, =, !=
SELECT *
FROM employees
WHERE phone_number = (SELECT phone_number
FROM employees
WHERE employee_id = 100);
SELECT *
FROM employees
WHERE hire_date = (SELECT hire_date
FROM employees
WHERE email = 'SKING');
SELECT *
FROM employees
WHERE hire_date < (SELECT hire_date
FROM employees
WHERE email = 'SKING');
SELECT *
FROM employees
WHERE hire_date >= (SELECT hire_date
FROM employees
WHERE hire_date = '06/01/03');
- 다중 행 서브 쿼리
- 서브 쿼리 SELECT 문에서 다중 행 결과를 메인 쿼리에 전달
- 단일 행 연산자는 사용할 수 없고, 다중 행 연산자만 사용 가능
다중 행 연산자 | 설명 | 예 |
IN | 서브 쿼리 결과 중 같은 값이 포함되어 있으면 TRUE | IN(100, 101) |
NOT IN | 서브 쿼리 결과 중 같은 값이 포함되어 있지 않으면 TRUE | NOT IN(100, 101) |
EXISTS | 서브 쿼리의 결과가 존재하면 TRUE | EXISTS(100) |
ANY(SOME) | 조건식을 하나라도 만족하면 TRUE (OR와 비슷) | ANY(100, 101) |
ALL | 조건식을 모두 만족하면 TRUE (AND와 비슷) | ALL(100, 101) |
* IN / NOT IN 연산자
SELECT *
FROM employees
WHERE salary IN (SELECT MAX(salary)
FROM employees
GROUP BY department_id);
SELECT *
FROM employees
WHERE salary NOT IN (SELECT MAX(salary)
FROM employees
GROUP BY department_id);
* EXISTS 연산자
SELECT *
FROM employees
WHERE EXISTS (SELECT *
FROM employees
WHERE employee_id = 100);
--
EXISTS 일 경우 예시 (EXISTS: 존재하다)
- WHERE문에 EXISTS는 서브쿼리 테이블의 결과물과 겹치는 데이터만 메인쿼리에 출력 (SELECT에 존재하는것출력)
EXISTS (SELECT 1
FROM TBL2 B
WHERE A.ID = B.ID)
-> 서브쿼리 결과와 겹치는 애들만 메인쿼리에 출력
--
NOT EXISTS 와 서브쿼리 예시
- WHERE 문에 NOT EXISTS는 서브쿼리 테이블의 결과물을 제외한 나머지를 메인쿼리에 출력
- 메인쿼리에서 서브쿼리의 결과물이랑 겹치는 애들을 제외! ( 차집합)
WHERE NOT EXISTS (SELECT 1
FROM TBL2 B
WHERE A.ID = B.ID)
-> 서브쿼리 결과를 제외하고 출력
* ANY / ALL 연산자
SELECT *
FROM employees
WHERE salary = ANY(6000, 10000, 12000);
SELECT *
FROM employees
WHERE salary <> ANY(6000, 10000, 12000);
SELECT *
FROM employees
WHERE salary != ANY(6000, 10000, 12000);
> 인라인 뷰(Inline View)
- FROM 절에 있는 서브쿼리가 인라인 뷰를 생성
- FROM 절에 직접 기술하여 효율적인 검색 가능
- FROM 절에 있는 서브쿼리에는 자주 별칭을 사용
SELECT *
FROM employees E, (SELECT department_id
FROM departments
WHERE department_name = 'IT') D
WHERE E.department_id = D.department_id;
SELECT *
FROM employees E, (SELECT department_id, AVG(salary) avg_sal
FROM employees
GROUP BY department_id) D
WHERE E.department_id = D.department_id
AND E.salary > D.avg_sal;
Summary
- 서브쿼리
- 하나의 SQL문 안의 SQL문
- 단일행 또는 복수행 비교 연산자와 함께 사용 가능
- 서브쿼리에서는 ORDER BY 사용 불가 (메인쿼리의 마지막 부분에서만 위치 가능하다)
- 서브쿼리는 메인쿼리의 테이블 칼럼 사용 가능하다. (메인쿼리에서는 서브쿼리의 칼럼 사용불가)
- 서브쿼리가 SQL 문에서 사용 가능한 곳
- SELECT, FROM WHERE, HAVING, ORDER BY 절
- INSERT문의 VALUES절
- UPDATE문의 SET절
- DELETE문은 사용 불가하다.
- 그 밖의 위치에서 사용 하는 서브 쿼리
- SELECT 절에 서브쿼리 사용 → 스칼라 서브쿼리 (Scalar Subquery)
- 한 행, 한 칼럼만을 반환
- 값 하나를 반환하는 서브쿼리, SELECT절에 사용하는 서브쿼리
- 스칼라 서브쿼리 대신 JOIN으로 동일한 결과 추출 가능
- 뷰(VIEW)
- 가상의 테이블, FROM절에 사용하는 뷰는 인라인 뷰 라고 한다.(실제 데이터 X)
- SQL이 실행될 때만 임시적으로 생성되는 동적 뷰 (일회성)
- 일반 뷰가 정적 뷰, 인라인 뷰는 동적
- 장점:
- 독립성: 테이블 구조 변경 자동 반영
- 편리성: 쿼리를 단순하게 작성 가능
- 보안성: 뷰를 생성할 때 칼럼을 제외할 수 있음
- SELECT 절에 서브쿼리 사용 → 스칼라 서브쿼리 (Scalar Subquery)
'Language > RDBMS' 카테고리의 다른 글
[DML_UPDATE] 데이터 변경 (0) | 2023.03.03 |
---|---|
[DML_INSERT] 데이터 삽입 (0) | 2023.03.03 |
[DML_SELECT] JOIN 연산 (0) | 2023.03.03 |
[DML_SELECT] Multi-Row Function (0) | 2023.03.03 |
[DML_SELECT] SQL 함수(숫자, 날짜, 변환, 일반) (0) | 2023.03.03 |