2026년 07월 05일 | DBMS Error 가이드
이 글에서 다루는 내용
42P20 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
42P20 windowing error 는?
PostgreSQL 에러 코드 42P20은 windowing error로, SQL 쿼리에서 윈도우 함수(Window Function)를 잘못 사용했을 때 발생합니다. 윈도우 함수는 OVER() 절과 함께 사용되며, ROW_NUMBER(), RANK(), LAG(), LEAD(), SUM() 등의 집계·분석 함수가 파티션 또는 정렬 기준에 따라 결과를 계산합니다. 이 에러는 윈도우 함수의 구문이 잘못되었거나, 지원하지 않는 방식으로 중첩 사용하거나, OVER() 절의 옵션이 상호 충돌할 때 주로 발생합니다.
주요 발생 원인
1. 윈도우 함수 내부에서 또 다른 윈도우 함수를 중첩 사용
PostgreSQL은 윈도우 함수 안에 다른 윈도우 함수를 직접 중첩하여 사용하는 것을 허용하지 않습니다. 예를 들어, SUM(ROW_NUMBER() OVER (...)) OVER (...) 형태로 작성하면 파서 단계에서 즉시 42P20 에러가 발생합니다. 이는 윈도우 함수의 평가 순서와 실행 계획상 논리적 모순이 생기기 때문이며, 반드시 서브쿼리나 CTE를 통해 분리해야 합니다.
2. ROWS/RANGE 프레임 옵션의 잘못된 조합
OVER() 절 내의 프레임 지정(ROWS BETWEEN ... AND ... 또는 RANGE BETWEEN ... AND ...)에서 시작점(start)이 종료점(end)보다 논리적으로 뒤에 오는 경우 에러가 발생합니다. 예를 들어 ROWS BETWEEN CURRENT ROW AND UNBOUNDED PRECEDING처럼 앞뒤가 뒤바뀐 프레임을 정의하면 PostgreSQL은 이를 유효하지 않은 윈도우 프레임으로 간주하고 42P20을 반환합니다. 프레임의 시작은 항상 종료보다 앞선 위치여야 한다는 규칙을 반드시 기억해야 합니다.
3. 집계 함수와 윈도우 함수의 혼용 오류
GROUP BY와 함께 사용할 때, 집계 함수(SUM, COUNT 등)의 결과를 윈도우 함수의 인자로 바로 전달하거나, WHERE 절 또는 GROUP BY 절 안에 윈도우 함수를 직접 사용하려는 시도가 이 에러를 유발합니다. 윈도우 함수는 SQL 실행 순서상 GROUP BY 및 HAVING 이후, ORDER BY 이전에 평가되므로, WHERE나 GROUP BY 절에서는 사용할 수 없습니다. 이 경우도 반드시 서브쿼리나 CTE로 감싸야 합니다.
해결 방법
원인 1 해결: 윈도우 함수 중첩 → CTE 또는 서브쿼리로 분리
잘못된 예시:
-- 42P20 에러 발생: 윈도우 함수 중첩 사용
SELECT
employee_id,
SUM(ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC))
OVER (PARTITION BY department_id) AS nested_window_error
FROM employees;
올바른 예시 (CTE 분리):
-- CTE를 이용해 단계적으로 분리
WITH ranked AS (
SELECT
employee_id,
department_id,
salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
FROM employees
)
SELECT
department_id,
SUM(rn) OVER (PARTITION BY department_id) AS sum_of_ranks
FROM ranked;
올바른 예시 (서브쿼리 분리):
-- 서브쿼리를 이용한 분리
SELECT
department_id,
SUM(rn) OVER (PARTITION BY department_id) AS sum_of_ranks
FROM (
SELECT
employee_id,
department_id,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
FROM employees
) sub;
원인 2 해결: 잘못된 프레임 옵션 수정
잘못된 예시:
-- 42P20 에러 발생: 프레임 시작/종료가 역전됨
SELECT
order_id,
order_date,
amount,
SUM(amount) OVER (
ORDER BY order_date
ROWS BETWEEN CURRENT ROW AND UNBOUNDED PRECEDING -- 잘못된 방향
) AS running_total
FROM orders;
올바른 예시:
-- 누적 합계: UNBOUNDED PRECEDING → CURRENT ROW (올바른 방향)
SELECT
order_id,
order_date,
amount,
SUM(amount) OVER (
ORDER BY order_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_total
FROM orders;
-- 슬라이딩 윈도우 예시: 앞 2행 ~ 현재행
SELECT
order_id,
order_date,
amount,
AVG(amount) OVER (
ORDER BY order_date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS moving_avg
FROM orders;
원인 3 해결: WHERE/GROUP BY 절에서 윈도우 함수 사용 시 서브쿼리로 분리
잘못된 예시:
-- 42P20 에러 발생: WHERE 절에 윈도우 함수 직접 사용
SELECT
employee_id,
department_id,
salary
FROM employees
WHERE ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) = 1;
올바른 예시:
-- 서브쿼리로 감싸서 WHERE 절에서 필터링
SELECT employee_id, department_id, salary
FROM (
SELECT
employee_id,
department_id,
salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
FROM employees
) ranked_employees
WHERE rn = 1;
-- CTE를 활용한 방법
WITH ranked_employees AS (
SELECT
employee_id,
department_id,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rnk
FROM employees
)
SELECT employee_id, department_id, salary
FROM ranked_employees
WHERE rnk <= 3; -- 부서별 상위 3명
예방 방법
1. 윈도우 함수 작성 전 실행 단계 순서를 반드시 숙지하기
SQL의 논리적 실행 순서는 FROM → WHERE → GROUP BY → HAVING → SELECT(윈도우 함수 평가) → ORDER BY → LIMIT 입니다. 윈도우 함수는 SELECT 단계에서만 평가되므로, WHERE, GROUP BY, HAVING 절에는 직접 사용할 수 없습니다. 복잡한 윈도우 함수 쿼리를 작성할 때는 항상 CTE(WITH 절)를 이용해 단계별로 나눠 작성하는 습관을 들이면 이 에러를 사전에 방지할 수 있습니다.
2. 프레임 옵션 사용 시 명시적으로 작성하고 방향성 검토하기
ROWS BETWEEN이나 RANGE BETWEEN 프레임을 사용할 때는 항상 시작 프레임 → 종료 프레임 순서로 PRECEDING에서 FOLLOWING 방향으로 작성해야 합니다. 코드 리뷰나 개발 단계에서 프레임 옵션을 생략하면 PostgreSQL의 기본값(RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)이 적용되므로, 의도한 동작을 보장하기 위해 항상 프레임을 명시적으로 지정하는 것이 Best Practice입니다. 또한, 팀 내 SQL 컨벤션 문서에 윈도우 함수 작성 규칙을 명시해두면 실수를 줄일 수 있습니다.
관련 에러
42883(undefined_function): 존재하지 않는 윈도우 함수 이름을 사용했을 때 발생합니다.42601(syntax_error):OVER()절의 구문 자체가 잘못 작성된 경우 발생하며,42P20과 혼동되기 쉽습니다.42803(grouping_error):GROUP BY없이 집계 함수와 일반 컬럼을 혼용했을 때 발생하며, 집계 함수와 윈도우 함수를 함께 사용하는 쿼리에서 자주 같이 나타납니다.42P19(invalid_recursion): 재귀 CTE에서 잘못된 참조가 있을 때 발생하며, CTE를 활용한 윈도우 함수 쿼리 작성 중 마주칠 수 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.