| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- is null
- having
- 트래블테크
- MAX
- date_format
- LIMIT
- inner join
- join
- order by
- SQL
- 도서추천
- 금융 플랫폼
- programmers
- where
- MySQL
- 서브쿼리
- IN
- ifnull
- GROUP BY
- 투자자산운용사
- Python
- IELTS
- Round
- SubQuery
- IS NOT NULL
- count
- 금융IT
- 해외결제
- 날짜 포맷
- alias
- Today
- Total
Every Step Matters
[SQL] SQL SELECT 쿼리 작성 순서와 실행 순서 정리 본문
SQL SELECT 쿼리 작성 시 보통 어떤 문법보다도 SELECT 문이 가장 먼저 나온다. 하지만 실제 SELECT 쿼리가 동작하는 실행 순서에서 SELECT 는 매우 늦게 실행된다.
SELECT 쿼리의 작성 순서와 실행 순서를 자세히 비교해보자.

쿼리 작성 순서와 실행 순서가 다른 이유 & 실행 순서가 중요한 이유
왜 쿼리 작성 순서와 실행 순서가 다른 것일까?
작성 시에는 사용자가 이해하기 쉬운 논리적 순서로 쿼리를 작성하지만,
실제 데이터베이스는 효율적인 처리를 위해 옵티마이저가 미리 지정된 최적의 순서로 데이터를 처리하기 때문이다.
이처럼 쿼리 실행 순서가 이미 정해져 있기 때문에, 같은 결과라도 어떻게 쿼리문을 작성하느냐에 따라 성능의 차이가 발생한다. 따라서 실행 순서를 정확히 알아야지 성능적으로 우수한 쿼리를 작성할 수 있다.
SELECT 쿼리 작성 순서
먼저 쿼리 작성 순서는 다음과 같다.
SELECT > FROM > JOIN(ON) > WHERE > GROUP BY > HAVING > ORDER BY > LIMIT
< SQL SELECT 쿼리 작성 순서 >
SELECT 컬럼명
FROM 테이블명
JOIN ~ ON 조인조건
WHERE 필터조건
GROUP BY 그룹핑할 컬럼
HAVING 그룹핑 후 필터조건
ORDER BY 정렬할 컬럼
LIMIT 최종 결과 개수;
SELECT 쿼리 실행 순서
반면 쿼리 실행 순서는 다음과 같다.
FROM > JOIN(ON) > WHERE > GROUP BY > HAVING > SELECT > DISTINCT > ORDER BY > OVER > LIMIT
---- 주요 순서만 본다면 다음과 같다 ----
FROM > JOIN ON > WHERE > GROUP BY > HAVING > SELECT > ORDER BY > LIMIT
< SQL SELECT 쿼리 실제 실행 순서 >
1. FROM : 조회할 테이블을 지정한다.
2. JOIN(ON) : 이후 JOIN을 실행하여 하나의 가상 테이블로 결합한다. ON은 조인기준 설정.
3. WHERE : 테이블에서 조건에 맞는 데이터를 필터링 한다.
4. GROUP BY : 선택한 컬럼을 기준으로 행을 그룹화 한다.
5. HAVING : 그룹화된 데이터에 조건을 적용한다.
6. SELECT : 결과에서 필요한 컬럼을 선택한다.
7. DISTINCT : 중복 행을 제거한다.
8. ORDER BY : 결과를 정렬한다.
9. OVER() : 행을 유지한 채 집계·순위 계산을 수행한다. (윈도우 함수 실행)
10. LIMIT : 반환할 행의 수를 제한한다.
위와 같은 실행 순서는 크게 3개로 분할해서 생각할 수 있다.
STEP 1. 테이블 인식 : FROM
STEP 2. 테이블 구조 : JOIN(ON) - WHERE - GROUP BY - HAVING (⭐중요⭐)
STEP 3. 테이블 조회 : SELECT - DISTINCT - ORDER BY - LIMIT
성능적으로 뛰어난 쿼리를 작성하기 위해서는?
STEP2(테이블 구조) 관련 절은 연산량과 성능을 결정짓는 핵심 절이다.
어떻게 쿼리를 짜는지에 따라 "연산 후 추출 VS 추출하기 전 필요한 것만 연산"으로 과정이 나뉠 수 있다.
TABLE_A 에서 WHERE '날짜' = '2023-01-01'인 행을 대상으로 TABLE_B와 ID를 기준으로 JOIN할 때
SELECT ID, 날짜
FROM TABLE_A A
JOIN TABLE_B B ON A.ID=B.ID
WHERE '날짜' = '2023-01-01'
만약 TABLE_A에 포함된 날짜범위가 2010~2023년이라고 가정했을 때 해당 쿼리는 작동은 하겠지만 필요한 컬럼 대비 연산량이 과도하게 많아진다는 문제가 있다.
(전체 테이블A에 대해 연산한뒤(JOIN) 조건에 맞는 것만 추출하는 WHERE절이 동작하기 때문)
따라서 경우에 따라 JOIN하기 전에 CTE처리를 하는 등 따로 테이블을 분리해서 처리하는 것을 고려할 필요가 있다.
Alias의 위치
다음과 같은 쿼리문이 있다.
SELECT product_id AS id, price_unit AS unit
FROM tutorial.excel_sql_inventory_data
WHERE price_unit < 3
ORDER BY product_id;
위의 쿼리는 Mode Analytics 사이트의 sql editor에서 무료로 실행해볼 수 있다.
테이블은 기본적으로 제공되는 Public Warehouse의 tutorial.excel_sql_inventory_data 테이블을 이용하였다.
1) 이때 ORDER BY에 ALIAS를 사용해보자.
SELECT product_id AS id, price_unit AS unit
FROM tutorial.excel_sql_inventory_data
WHERE price_unit < 3
ORDER BY id; -- alias 사용
해당 쿼리는 아무 문제 없이 실행된다. ORDER BY 절은 SELECT 절 이후에 실행되기 때문에 id가 product_id의 별칭이라는 것을 시스템이 이해할 수 있다.
2) 이번에는 WHERE 절에 ALIAS를 사용해보자.
SELECT product_id AS id, price_unit AS unit
FROM tutorial.excel_sql_inventory_data
WHERE unit < 3 -- alias 사용
ORDER BY product_id;
아래와 같은 에러가 떴다. (Looks like something went wrong with your query.)

WHERE절은 SELECT보다 먼저 실행되기 때문에 unit이 price_unit의 별칭이라는 것을 시스템이 알지 못한다.
추천글
더 자세한 예시와 함께 실행 순서를 알고 싶다면 아래 글을 참고하면 좋을 것 같다.
https://myjamong.tistory.com/172#google_vignette
[Oracle] SQL SELECT 쿼리 실행 순서 처리 과정 :: 마이자몽
SELECT 쿼리 실행 순서 SQL 쿼리문을 작성할때 사용되는 WHERE, GROUP BY, ORDER BY 절과 같은 구문을 실행하는데 순서가 존재합니다. 이 순서에 의해서 쿼리가 처리되고 어떻게 쿼리문을 작성하느냐에 따
myjamong.tistory.com
Reference
https://myjamong.tistory.com/172#google_vignette
'Database > SQL' 카테고리의 다른 글
| [프로그래머스 SQL Lv.2] 조건에 맞는 도서와 저자 리스트 출력하기 (MySQL) (0) | 2026.01.04 |
|---|---|
| [MySQL] MySQL 현재 날짜 및 시간 출력 방법 (0) | 2026.01.03 |
| [SQL] IN과 EXISTS의 차이 (0) | 2025.12.07 |
| [프로그래머스 SQL Lv.1] 잡은 물고기 중 가장 큰 물고기의 길이 구하기 (MySQL) (0) | 2025.12.03 |
| [프로그래머스 SQL Lv.2] 중복 제거하기 (MySQL) (0) | 2025.12.03 |