[프로그래머스 SQL SOP] WHERE vs HAVING: 실행 순서가 쿼리 성능을 지배한다

이성진·2026년 3월 27일

프로그래머스 SQL

목록 보기
4/7

최적화 철학 회고
SQL 문제를 풀면서, 무거운 그룹화(GROUP BY) 연산을 수행하기 전에 필터링(WHERE)을 먼저 걸어두는 것이 연산 속도 측면에서 압도적으로 이득일 것이라 판단했다. 이 생각은 데이터베이스 최적화 관점에서 100% 정답이었다.
하지만 놀라운 점은, 이것이 개발자의 '선택사항'이 아니라 SQL이라는 언어 자체가 성능 최적화를 강제하기 위해 만들어둔 '엄격한 문법적 실행 파이프라인'이라는 사실이다. 오늘은 그 파이프라인의 뼈대와 WHERE, HAVING의 본질적인 차이를 정리한다.

📌 SQL은 작성된 순서대로 실행되지 않는다

우리는 코드를 위(SELECT)에서부터 아래로 읽고 작성하지만, 데이터베이스 엔진(Optimizer)은 완전히 다른 순서로 쿼리를 조립하고 실행한다. 이 절대적인 실행 순서를 모르면 쿼리 최적화는 불가능하며, 잦은 문법 에러(Syntax Error)에 시달리게 된다.

⚙️ SQL의 절대적 실행 파이프라인 (Execution Order)

  1. FROM / JOIN (데이터 탐색): "어느 테이블에서 데이터를 가져올 것인가?"
  2. WHERE (사전 필터링): "가져온 원본 데이터 중 조건에 안 맞는 행(Row)은 버리자!"
  3. GROUP BY (그룹화 연산): "살아남은 데이터들을 특정 기준(ID 등)으로 끼리끼리 묶자."
  4. HAVING (사후 필터링): "묶어서 집계해 보니 조건에 미달하는 그룹이 있네? 버리자!"
  5. SELECT (데이터 추출): "최종적으로 화면에 보여줄 컬럼만 선택하자."
  6. ORDER BY (정렬): "결과를 예쁘게 정렬하자."

🚨 WHERE vs HAVING: 필터링 시점의 결정적 차이

두 키워드 모두 데이터를 걸러내는(Filtering) 역할을 하지만, 파이프라인 상의 '시점'이 완전히 다르다. 이 둘을 혼동하면 치명적인 성능 저하나 논리 오류가 발생한다.

1. WHERE (사전 필터링)

  • 실행 시점: GROUP BY로 데이터를 묶기 .
  • 역할: 원본 테이블의 날것(Raw Data) 상태에서 개별 행(Row)들을 걸러낸다.
  • 최적화 관점: 여기서 최대한 많은 데이터를 걸러내야, 다음 단계인 GROUP BY 연산에 들어가는 메모리와 CPU 비용이 비약적으로 줄어든다. (예: ADDRESS LIKE '서울%'로 서울 식당만 미리 남겨두기)
  • 주의: WHERE 절 안에는 AVG(), COUNT() 같은 집계 함수를 절대 쓸 수 없다. 아직 묶이지 않았기 때문이다.

2. HAVING (사후 필터링)

  • 실행 시점: GROUP BY 연산이 모두 끝난 .
  • 역할: 이미 끼리끼리 묶여서 연산(AVG, SUM 등)이 끝난 결과 그룹을 걸러낸다.
  • 사용 예시: "그룹화하여 계산한 리뷰 평균 점수가 4.0 이상인 식당만 구하세요." 라는 조건은 사전에 알 수 없고 묶어봐야 알 수 있으므로 무조건 HAVING을 써야 한다. (HAVING AVG(SCORE) >= 4.0)

💡 최종 결론 (SOP)

"GROUP BY를 먼저 쓰고 WHERE를 나중에 쓰면 안 되나요?"

불가능하다. SQL은 애초에 개발자가 무거운 연산(GROUP BY)을 쓸데없이 방대한 데이터에 적용하는 참사를 막기 위해, WHERE로 먼저 모수를 줄이고 나서 GROUP BY를 하도록 문법적 순서를 강제해 두었다.

단순히 정답을 맞히는 것을 넘어 데이터베이스 엔진 내부의 파이프라인을 이해하고 쿼리를 작성하는 것. 이것이 쿼리 작성 SOP의 가장 중요한 첫 단추이다.

profile
알고리즘과 cs지식 학습

0개의 댓글