반응형
해당 글에서는 서브쿼리와 WITH절에 대해서 이해하고 각각의 종류들에 대해서 상세하게 이해를 돕기 위한 목적으로 작성한 글입니다.
1) 서브 쿼리(Subquery)
💡 서브쿼리(subquery) 란?
- ‘하나의 SQL 문장 안에서 다른 SQL 문장을 사용하는 것'을 의미합니다. 서브 쿼리는 메인 쿼리에 종속된 쿼리로 메인 쿼리의 결과로 필요로 할 때 사용합니다.
- 일반적으로 WHERE 또는 HAVING 절에서 사용되며 메인 쿼리와 서브쿼리 사이에는 ‘괄호’로 구분되며 메인 쿼리의 결과에 따라 다른 결과를 반환하는 데 사용됩니다.
1. 서브 쿼리의 사용범위
💡 서브쿼리는 WHERE, HAVING, FROM, SELECT 등에서 사용할 수 있으며 ‘단일’ 혹은 ‘중첩’하여 사용이 가능합니다.
사용 위치 | 서브 쿼리 종류 |
SELECT | 스칼라 서브쿼리 |
FROM | 인라인 뷰 |
WHERE | 일반 서브쿼리, 스칼라 서브쿼리 |
HAVING | 일반 서브쿼리 |
[ 더 알아보기 ]
💡 스칼라 서브쿼리는 WHERE 뿐만 아니라 SELECT 절에서 사용이 되는가?
- 스칼라 서브쿼리는 ‘하나의 값’을 반환하는 서브쿼리를 의미합니다. 주로는 SELECT 절에서 사용되며 ‘하나의 열(컬럼)’처럼 사용이 됩니다.
💡 [참고] WHERE 절에서 스칼라 서브쿼리를 이용하는 예시
SELECT *
FROM table1 t1
WHERE t1.salary >= (SELECT AVG(t2.salary) FROM table2 t2)
2) 일반 서브 쿼리(subquery)
💡 일반 서브쿼리(subquery) 란?
- 메인 쿼리의 ‘조건’으로 사용이 되며 WHERE, HAVING절에서 사용되는 서브쿼리를 의미합니다.
1. 구조 및 수행 순서
1.1. 서브 쿼리 구조
-- Subquery
SELECT *
FROM 테이블1
WHERE 테이블1.열1 > (SELECT 테이블2.COUNT(*) FROM 테이블2)
-- Subquery Example
SELECT *
FROM table1 t1
WHERE t1.salary >= (SELECT AVG(t2.salary) FROM table2 t2)
1.2. 서브 쿼리 수행 순서
💡 서브 쿼리 수행 순서 (FROM → WHERE → 서브쿼리 → SELECT)
1. FROM절에서 지정된 테이블에서 데이터를 가져옵니다.
2. WHERE절에서 조건을 만족하는 데이터를 필터링합니다.
3. WHERE절 안에서 서브쿼리를 수행합니다.
4. WHERE절에서 서브쿼리의 결과를 사용하여 SELECT절에서 최종 결과를 출력합니다.
💡WHERE 절 안에서 사용되는 서브쿼리는 WHERE 절에서 가장 나중에 수행되며 최종 결과에 영향을 미치는 중요한 역할을 합니다.
2. 단일행 서브 쿼리(Single Row Subquery)
💡 단일행 서브 쿼리(Single Row Subquery)란?
- 서브 쿼리의 결과가 ‘하나의 행만'을 반환하는 것을 의미합니다. 반환되는 값은 하나의 컬럼에 ‘저장’ 또는 ‘단일 비교 연산자’를 통하여 비교하여 사용됩니다.
2.1. 단일 비교 연산자 종류
단일 비교 연산자 | 설명 |
= | 서브쿼리의 결과와 메인 쿼리의 조건이 같을 때 참 |
> | 서브쿼리의 결과가 메인 쿼리의 조건보다 클 때 참 |
< | 서브쿼리의 결과가 메인 쿼리의 조건보다 작을 때 참 |
>= | 서브쿼리의 결과가 메인 쿼리의 조건보다 크거나 같을 때 참 |
<= | 서브쿼리의 결과가 메인 쿼리의 조건보다 작거나 같을 때 참 |
<> | 서브쿼리의 결과와 메인 쿼리의 조건이 다를 때 참 |
!= | 서브쿼리의 결과와 메인 쿼리의 조건이 다를 때 참 |
2.2. 사용 예시
💡 사용 예시
- table1에서 column1이 최대값인 행을 찾아 그 column1과 해당 행의 column2를 반환합니다.
SELECT column1, column2
FROM table1
WHERE column1 = (SELECT MAX(column1) FROM table1)
3. 다중행 서브 쿼리(Muti Row Subquery)
💡 다중행 서브 쿼리(Muti Row Subquery)란?
- 서브쿼리의 결과가 ‘여러 개의 행’을 반환하는 것을 의미합니다. 반환되는 값은 여러개의 컬럼에 ‘저장’ 또는 ‘다중 비교 연산자’를 통하여 비교하여 사용됩니다.
3.1. 다중행 비교 연산자 종류
다중행 비교 연산자 | 내용 |
ANY | 서브쿼리가 반환하는 여러 행 중에서 하나라도 조건을 만족하면 참 |
ALL | 서브쿼리가 반환하는 모든 행이 조건을 만족하면 참 |
IN | 서브쿼리가 반환하는 결과 중 하나와 일치하면 참 |
EXISTS | 서브쿼리가 반환하는 결과가 존재하면 참 |
3.2. 사용 예시
💡 사용 예시
- table1의 column1 값이 table2의 column1 값 중 하나와 일치하는 경우 해당 row를 반환하며, table2의 column2 값이 'value'인 행만 비교합니다.
SELECT *
FROM table1
WHERE column1 IN (SELECT column1 FROM table2 WHERE column2 = 'value');
3) 스칼라 서브쿼리(Scalar Subquery)
💡 스칼라 서브쿼리(Scalar Subquery)란?
- 메인 쿼리의 ‘하나의 값(열, 컬럼)’으로 반환하며 SELECT 절에서 사용되는 서브쿼리를 의미합니다.
1. 구조 및 수행 순서
1.1. 스칼라 서브 쿼리 구조
-- Scalar Subquery
SELECT 테이블1.열1, (SELECT 테이블2.열1 FROM 테이블2 )
FROM 테이블1
WHERE 테이블1.열1 = 'example'
1.2. 스칼라 서브 쿼리 수행 순서
💡 스칼라 서브 쿼리 수행 순서 (FROM → WHERE → 스칼라 서브 쿼리 → SELECT)
1. FROM절에 지정된 테이블에서 데이터를 가져온다.
2. WHERE절에서 조건을 만족하는 데이터를 필터링한다.
3. SELECT절에서 스칼라 서브쿼리를 수행한다.
4. SELECT절을 수행하여 스칼라 서브쿼리의 결과를 사용하여 최종 결과를 생성한다.
2. 사용예시
💡사용 예시
- 해당 SQL 쿼리는 table1의 id가 'adjh54'인 행을 찾아 그 name과 table2의 name을 반환하는 쿼리입니다.
- table2의 name은 t2로 별칭을 지정하고, 스칼라 서브쿼리로 사용되어 table2에서 첫 번째 name 값을 반환합니다.
-- Scalar Subquery Example
SELECT t1.name, (SELECT t2.name FROM table2 t2)
FROM table1 t1
WHERE t1.id = 'adjh54'
4) 인라인 뷰(Inline View)
💡 인라인 뷰(Inline View) 란?
- 서브쿼리가 ‘하나의 테이블(가상 테이블)’로 만들어져 메인 쿼리에서 이를 사용하며 FROM절에서 사용되는 서브쿼리를 의미합니다.
- 새로운 가상의 테이블로 사용되기에 ‘AS(Alias)’를 통해 별칭을 지정해야 한다.
[ 더 알아보기 ]
💡 SQL Alias 란?
- 특정 칼럼이나 테이블에 대하여 별칭을 부여하는것을 의미합니다. 이를 통해 편리하게 컬럼이나 테이블을 참조할 수 있습니다.
1. 구조 및 수행 순서
1.1. 인라인 뷰 구조
-- Inline View
SELECT alias.열2, 테이블2.열2
FROM (SELECT 테이블1.열2
FROM 테이블1) AS alias
, 테이블2
WHERE alias.열1 = 테이블2.열1
1.2. 인라인 뷰 수행순서
💡 인라인 뷰 수행 순서 (FROM: 인라인 뷰 → WHERE → SELECT)
1. FROM 절에서 인라인 뷰로 지정된 서브쿼리가 수행됩니다.
2. 인라인 뷰의 결과를 사용하여 SELECT 문의 나머지 부분이 수행됩니다.
3. 최종 결과가 생성됩니다.
2. 사용 예시
💡사용 예시
- ‘employees’ 테이블에서 salary가 10000 이상인 직원들의 부서 ID와 연봉을 가져오는 쿼리입니다. 이를 위해, employees 테이블에서 salary가 10000 이상인 직원들의 부서 ID와 연봉을 먼저 가져온 다음 이를 temp라는 가상의 테이블로 생성합니다. 이후, temp 테이블에서 부서 ID별로 연봉의 평균을 구하는 쿼리를 실행합니다.
-- Inline View Example
SELECT department_id, AVG(salary)
FROM (
SELECT department_id, salary
FROM employees
WHERE salary >= 10000
) AS temp
GROUP BY department_id;
5) WITH 절
💡 WITH 절 이란?
- 서브쿼리를 ‘미리 정의’하여 복잡한 쿼리를 간단하게 만드는 방법입니다. 이를 통해 쿼리의 가독성을 높이고 성능을 향상할 수 있습니다.
- WITH 절은 일반적으로 ‘CTE(Common Table Expression)’라고도 불립니다.
[ 더 알아보기 ]
💡 CTE(Common Table Expression) 란?
- WITH 절을 이용하여 하나 이상의 임시 테이블을 정의할 때 사용하는 구문입니다. 이를 통해 복잡한 쿼리를 더 간단하게 작성할 수 있으며, 가독성과 유지보수성을 높일 수 있습니다.
1. WITH 절 장점
장점 | 설명 |
시스템 부하 절약 | 메인 쿼리에서 서브쿼리를 반복적으로 사용해야 하는 경우에도 시스템 부하를 줄일 수 있습니다. |
가독성 | 복잡한 쿼리를 작성할 때, 서브쿼리를 WITH절로 정의하면 가독성이 향상됩니다. |
재사용성 | WITH절에서 정의한 서브쿼리는 해당 쿼리에서만 사용하는 것이 아니라, 다른 쿼리에서도 재사용이 가능합니다. |
성능 | WITH절은 성능을 향상시키는 경우가 있습니다. 서브쿼리를 실행할 때마다 같은 데이터를 다시 읽어오는 것이 아니라, WITH절을 사용하여 임시 테이블에 저장해두고 필요할 때마다 호출하기 때문입니다. |
2. WITH 절 구조 및 수행순서
2.1. WITH 절 구조
💡 여기서 cte_name은 CTE의 이름을 지정하고, subquery는 CTE로 정의될 서브쿼리입니다. 이렇게 정의된 CTE는 ‘SELECT 문’에서 참조될 수 있습니다.
WITH
cte_name1 AS (subquery1),
cte_name2 AS (subquery2),
cte_name3 AS (subquery3)
SELECT ...
2.2. 수행 순서
💡 WITH 절 수행 순서 (CTE의 서브쿼리 실행 → 임시 테이블 생성 → 메인 쿼리 수행)
1. WITH 절의 서브쿼리들을 실행하여 임시 테이블을 생성합니다.
2. 임시 테이블을 사용하여 메인 쿼리를 실행합니다.
3. 사용 예시
💡 해당 쿼리는 sales_by_month라는 CTE를 정의하고 이를 사용하여 매출이 10,000달러 이상인 달을 찾는 쿼리입니다.
WITH sales_by_month AS (
SELECT
EXTRACT(YEAR FROM sale_date) AS year,
EXTRACT(MONTH FROM sale_date) AS month,
SUM(sale_amount) AS total_sales
FROM sales
GROUP BY year, month
)
SELECT *
FROM sales_by_month
WHERE total_sales > 10000;
[ 더 알아보기 ]
💡 EXTRACT() 함수란?
- DATE 데이터 타입에서 년, 월, 일, 시간, 분, 초 등을 추출하여 반환하는 함수입니다.
💡 SUM() 함수란?
- 주어진 열의 값을 모두 더해서 총합을 반환하는 함수입니다.
오늘도 감사합니다. 😀
반응형
'DB > 이론 및 문법' 카테고리의 다른 글
[DB/Postgres] PL/pgSQL 구성하기 -2 : DBeaver 기반 구축 및 활용 (0) | 2023.04.17 |
---|---|
[DB/Postgres] 테이블 스캔 -1 : 전체, 인덱스(전체, 범위, 고유, 루스, 병합) 스캔 (2) | 2023.04.09 |
[DB/Postgres] GROUP BY, ORDER BY, LIMIT 이해하기 -1 (0) | 2023.04.08 |
[DB/Postgres] PL/pgSQL이해하기 -1 : Function, Stored Procedure (0) | 2023.04.08 |
[DB/Postgres] 조인(JOIN) 이해하기 : 내부/외부 조인, UNION/UNION ALL (1) | 2023.04.04 |