1. 서브쿼리
1) 개요
- 하나의 SQL문 안에 포함되어 있는 또 다른 SQL문
- 메인쿼리 기준으로 여러 개의 서브 쿼리 사용 가능
- 서브쿼리는 하나의 SELECT 문장으로, 괄호로 둘러쌓인 형태
2) 분류(메인쿼리와 연관성 여부)
- Un-Correlated(비연관) 서브쿼리
- Correlated(연관) 서브쿼리
3) 종류
- 스칼라 서브쿼리
- 인라인 뷰
- 중첩 서브쿼리(Nested Subquery)
4) 사용 시 주의사항
- 서브쿼리 사용 시 괄호로 감싸서 사용
- 서브쿼리는 단일 행(Single Row) 또는 복수 행(Multiple Row) 비교 연산자와 함께 사용 가능
- 단일 행 비교 연산자는 서브쿼리의 결과가 반드시 1건 이하이여야 하고 복수 행 비교 연산자는 서브쿼리의 결과 건수와 상관 없음
- 서브쿼리에서는 ORDER BY를 사용하지 못함
2. 스칼라 서브쿼리(SELECT 절)
1) 개요
- 메인쿼리의 SELECT 절에 위치한 서브 쿼리
- SELECT 절에서 마치 하나의 컬럼이나 표현식 처럼 사용함
- 서브쿼리에 별칭(Alias)를 주는 것이 일반적(하나의 컬럼 역할을 하기 때문)
- 한 행, 한 컬럼(1 Row, 1 Column)만을 반환
- 서브쿼리 내에서 메인쿼리와 조인 가능
- 성능 상 좋지 않기 때문에 과도한 사용은 자제
2) 예시
- 부서명 가져오기
SELECT a.employee_id, a.first_name || a.last_name employee_name
,a.department_id
,(SELECT b.department_name
FROM departments b
WHERE a.department_id = b.department_id) department_name
FROM employees a
ORDER BY 1;
- 오류 구문
SELECT a.employee_id, a.first_name || a.last_name employee_name
,a.department_id
,(SELECT **b.department_name, b.location_id**
FROM departments b
WHERE a.department_id = b.department_id) department_name
FROM employees a
ORDER BY 1;
-- 2개의 컬럼 값을 가져오므로 오류가 발생함
- 스칼라 서브쿼리 vs. 조인
-. 스칼라 서브쿼리
SELECT a.employee_id, a.first_name || a.last_name emp_name, a.department_id
,(SELECT department_name
FROM departments b
WHERE a.department_id = b.department_id) dept_name
FROM employees a
ORDER BY 1;
-- 사번 178번 킴벌리 그랜트 조회 가능
-. 내부조인(INNER JOIN)
SELECT a.employee_id, a.first_name || a.last_name emp_name, a.department_id
,b.department_name
FROM employees a, departments b
WHERE a.department_id = b.department_id
ORDER BY 1;
-- 사번 178번 킴벌리 그랜트 조회 불가
-- (WHERE 절에서 INNER JOIN으로 실행 되었기 때문)
-. 외부조인(LEFT JOIN)
SELECT a.employee_id, a.first_name || a.last_name emp_name, a.department_id
,b.department_name
FROM employees a
LEFT JOIN departments b
ON a.department_id = b.department_id
ORDER BY 1;
-- 사번 178번 킴벌리 그랜트 조회 가능(LEFT JOIN으로 null 값 조회 가능)
3. 인라인 뷰(FROM 절)
1) 개요
- 메인쿼리의 FROM 절에 위치
- 서브쿼리 자체가 마치 하나의 테이블 처럼 동작
- 서브쿼리가 최종 반환하는 로우와 컬럼, 표현식 수는 1개 이상 가능
- 서브쿼리에 대한 별칭(Alias)은 반드시 명시
- 메인쿼리와 조인 조건은 메인쿼리의 WHERE 절에서 처리가 일반적
2) 예시
SELECT a.employee_id, a.first_name || a.last_name employee_name
,a.department_id, c.dept_name
FROM employees a
,(SELECT b.department_id, b.department_name dept_name
FROM departments b) c
WHERE a.department_id = c.department_id
ORDER BY 1;
3) LATERAL
- 서브쿼리 내에서 조인이 불가하였으나 LATERAL을 이용하면 조인 가능
- -. AS-IS (LATERAL 미사용)
SELECT a.employee_id, a.first_name || a.last_name employee_name
,a.department_id, c.dept_name
FROM employees a
,**(SELECT b.department_id, b.department_name dept_name
FROM departments b
WHERE a.department_id = b.department_id) c**
ORDER BY 1;
-- 서브쿼리 내에서 조인 조건 불가(오류 발생)
**-. TO-BE (LATERAL 사용)**
SELECT a.employee_id, a.first_name || a.last_name employee_name
,a.department_id, c.dept_name
FROM employees a
,**LATERAL
(SELECT b.department_id, b.department_name dept_name
FROM departments b
WHERE a.department_id = b.department_id) c**
ORDER BY 1;
-- 오라클 12c 이후 버전에서 LATERAL을 사용해 서브쿼리 내 조인 가능
4. 중첩 서브쿼리 (Nested Subquery)
1) 개요
- 메인쿼리의 WHERE 절에 위치
- 서브쿼리가 조건절의 일부로 사용됨
- 서브쿼리 최종 반환 값과 메인쿼리 테이블의 특정 컬럼 값을 비교 시 사용
- 서브쿼리가 최종 반환하는 로우와 컬럼
- 조건절의 일부이므로 서브쿼리에 대한 별칭(Alias) 사용 불가
- 서브쿼리 내에서 메인쿼리와 조인 가능
2) 예시
SELECT *
FROM departments
WHERE department_id IN
(SELECT department_id
FROM employees);
SELECT *
FROM departments a
WHERE EXISTS
(SELECT 1
FROM employees b
WHERE a.department_id = b.department_id);
'Data > SQL' 카테고리의 다른 글
SQL 실무 : 나이, 연령대, 연령대별 회원수 계산 (0) | 2022.02.17 |
---|---|
SQL 실무 : 매출 누계, 전년동기 증감율(YoY) 계산 (1) | 2022.02.10 |
SQL 고급 : 집계 함수 vs. 윈도우 함수 비교 (0) | 2022.02.09 |
SQL vs. Pandas 비교 (2) - JOIN, PIVOT, WINDOW FUNCTIONS (0) | 2022.02.09 |
SQL vs. Pandas 비교 (1) - SELECT, WHERE, GROUP BY, LIMIT (0) | 2022.01.25 |