SQL을 작성할 때 우리는 SELECT, FROM, WHERE, GROUP BY, ORDER BY 순으로 코드를 작성한다. 하지만 실제로 SQL 쿼리는 우리가 작성한 순서와 다르게 실행되는데, 이 실행 순서를 이해하는 것은 효율적인 쿼리 작성, 디버깅, 성능 최적화에 매우 중요하다.
쿼리 작성순서와 실행순서는 어떻게 다를까?

우선 우리가 SELECT 구문을 작성할 때는 다음과 같은 순으로 작성한다.
SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT
그러나 실제 내부에서 일어나는 실행 순서는 다음과 같다.
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
- FROM / JOIN: 데이터를 가져올 테이블을 결정
- WHERE: 행 단위로 조건을 걸어 데이터를 필터링
- GROUP BY: 데이터를 그룹화하여 집계할 준비
- HAVING: 그룹화된 데이터에 조건을 걸어 필터링
- SELECT: 실제로 출력할 컬럼을 결정
- DISTINCT: 중복된 행을 제거
- ORDER BY: 결과를 정렬
- LIMIT / OFFSET: 출력할 행의 수를 제한
실행 순서가 다르다는건 알겠는데, 어떻게 실행되는지까지 알아야 하나요?


수학 공식을 이해하고 푸는 것과 외워서 푸는 것이 다르듯 쿼리의 실행순서를 이해하면 좋은 이유는 아주 많다. 대표적 예를 들자면:
1. 쿼리 작성의 정확성
WHERE 절은 행 단위로 조건을 적용하는 반면, HAVING 절은 그룹 단위로 조건을 적용한다. 따라서 집계 함수(예: COUNT, SUM)를 WHERE에서 사용하면 오류가 발생할 수 있다.
SELECT department, COUNT(*) AS emp_count
FROM employees
WHERE COUNT(*) > 5
GROUP BY department;
위 쿼리는 오류를 발생시킨다. 이유는 COUNT(*)는 GROUP BY 이후에 계산되므로, WHERE 절에서 사용할 수 없다. 이를 해결하려면 HAVING 절을 사용해야 한다.
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
2. 쿼리 성능 최적화
데이터를 조기에 필터링하면 처리해야 할 데이터 양이 줄어들어 성능이 향상한다. 예를 들어, WHERE 절에서 먼저 조건을 걸면 GROUP BY나 SELECT에서 처리할 데이터가 줄어든다.
-- 예: 급여 5000 이상 직원만 그룹화
SELECT department, COUNT(*) AS emp_count
FROM employees
WHERE salary >= 5000 -> 조기 필터링
GROUP BY department;
- 만약 WHERE를 쓰지 않고 GROUP BY 후 필터링하면, 모든 데이터를 먼저 그룹화 → 메모리 사용량 증가
- 따라서 WHERE에서 먼저 조건을 거는 것이 효율적
3. 복잡한 쿼리 작성 시 오류 방지
SELECT 절에서 정의한 별칭(alias)은 WHERE나 HAVING 절에서 사용할 수 없다. 이는 실행 순서에 따른 제한이다.
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING emp_count > 5; -- emp_count는 HAVING에서 바로 사용 불가
위처럼 작성하면 HAVING 절에서 오류가 난다. 올바르게 사용하기 위해선 아래와 같이 작성해야 한다.
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5; -- 집계 함수를 직접 사용
추가로 alias를 HAVING에서 쓰고 싶다면 아래와 같이 CTE나 서브쿼리를 사용해야 한다.
WITH dept_count AS (
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
)
SELECT department, emp_count
FROM dept_count
WHERE emp_count > 5;
하지만 이 경우, 쿼리 실행이 두 단계로 분리되기 때문에 대규모 연산의 경우 성능(시간복잡도, 메모리 사용량)에 영향이 생길 수 있다.
- CTE 쿼리 실행
→ employees 전체를 읽고, GROUP BY 수행 후
→ 임시 테이블(dept_count) 형태로 메모리에 저장 - 외부 SELECT 실행
→ dept_count에서 WHERE emp_count > 5 조건을 적용
이렇듯 데이터의 규모가 클수록 효율적으로 정보를 불러오는 것이 중요하기에, 반드시 실행순서를 이해하고 넘어가야 한다.
'자격증 공부 > PCSQL' 카테고리의 다른 글
| [PCSQL] 문자열 추출 함수 정리 (0) | 2025.10.17 |
|---|---|
| [PCSQL] 우유와 요거트가 담긴 장바구니 (MySQL) (0) | 2025.10.15 |
| [PCSQL] 프로그래머스 - 대장균들의 자식의 수 구하기(MySQL) (0) | 2025.10.09 |
| [PCSQL] DATE_FORMAT 날짜 포맷 (0) | 2025.10.04 |
| [PCSQL] SQL 핵심 문법 정리(요약 PDF 有) (0) | 2025.10.04 |