0Pricing
Coding Interview Prep · 강의

윈도 결과로 필터링하기

윈도 함수를 하위 쿼리나 CTE로 감싸야 필터링할 수 있는 이유를 알아봅니다.

윈도 결과로 필터링하기은(는) CoddyKit의 무료 Coding Interview Prep 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Coding Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

WHERE에서 윈도 결과를 걸러낼 수 없는 이유

면접에서 자주 나오는 "함정"입니다. WHERE ROW_NUMBER() OVER (...) = 1을 작성하면 오류가 발생합니다. 윈도 함수는 WHERE, GROUP BY, HAVING에서 사용할 수 없습니다.

이유는 논리적 실행 순서에 있습니다. WHERE는 윈도 함수가 평가되기 전에 실행되어 행을 선택합니다. 윈도 결과는 아직 계산되지 않았으므로 조건에서 참조할 수 없습니다.

실행 순서 설명

윈도 함수는 전용 단계에서 계산됩니다. 이 단계는 FROM, WHERE, GROUP BY, HAVING 다음에 오고, 최종 ORDER BY와 LIMIT 이전에 옵니다.

따라서 WHERE가 실행되는 순간에는 순위나 행 번호가 아직 존재하지 않습니다. 이를 조건으로 걸러내려면 먼저 윈도 계산이 끝나도록 한 다음, 생성된 열을 외부 쿼리 계층에서 걸러내야 합니다.

하위 쿼리로 감싸는 패턴

표준 해결법은 내부 쿼리(파생 테이블)에서 윈도 함수를 계산하고, 그 결과에 별칭을 지정한 다음, 외부 WHERE에서 해당 별칭을 조건으로 사용하는 것입니다.

파생 테이블에는 반드시 별칭이 있어야 합니다(여기서는 t). 면접관은 별칭을 빠뜨리는 지원자를 눈여겨봅니다. 이제 rn은 외부 쿼리에서 비교할 수 있는 일반 열이 됩니다.

SELECT *
FROM (
  SELECT
    name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
  FROM employees
) t
WHERE rn = 1;

CTE 패턴(더 깔끔한 경우가 많음)

공통 테이블 표현식은 더 읽기 쉬운 구조로 같은 작업을 수행합니다. WITH 단계에서 순위를 정의한 다음 주 쿼리에서 그 결과를 걸러냅니다.

기능적으로는 하위 쿼리와 같지만, 의도가 위에서 아래로 읽히기 때문에 면접관은 실시간 코딩에서 보통 CTE를 더 선호합니다.

WITH ranked AS (
  SELECT
    name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
  FROM employees
)
SELECT name, department, salary
FROM ranked
WHERE rn = 1;

실습 예제: 그룹별 상위 N개

가장 자주 나오는 윈도 문제는 "부서별로 급여가 가장 높은 직원 3명"입니다. CTE 안에서 순위를 매긴 다음, 바깥에서 rn <= 3인 행만 남깁니다.

동률 처리 방식에 따라 순위 함수를 선택하세요. ROW_NUMBER는 부서마다 정확히 3행으로 제한하고, 경계에서 동률인 행도 포함해야 한다면 RANK/DENSE_RANK로 바꾸세요.

WITH ranked AS (
  SELECT department, name, salary,
         ROW_NUMBER() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rn
  FROM employees
)
SELECT department, name, salary
FROM ranked
WHERE rn <= 3
ORDER BY department, rn;

실습 예제: 누적 합계 걸러내기

감싸기 패턴은 순위에만 사용하는 것이 아닙니다. 누적 합계, 이동 평균, LAG 차이와 같은 모든 윈도 결과도 같은 방식으로 걸러내야 합니다.

여기서는 누적 잔액을 계산한 다음, 처음으로 1000을 초과한 행만 남깁니다. 조건은 윈도 계층 바깥에 있습니다.

WITH balances AS (
  SELECT
    account_id, txn_date, amount,
    SUM(amount) OVER (
      PARTITION BY account_id ORDER BY txn_date
    ) AS running_balance
  FROM transactions
)
SELECT *
FROM balances
WHERE running_balance > 1000;

QUALIFY: 일부 데이터베이스의 지름길

스노플레이크, BigQuery, 테라데이타, DuckDB는 윈도 결과를 직접 걸러내는 QUALIFY 절을 제공합니다. 감싸기가 필요 없으며, 원하는 위치인 윈도 함수 실행 후에 동작합니다.

폭넓은 이해를 보여주기 위해 QUALIFY를 언급하되, 이것은 SQL 표준이 아니며 PostgreSQL, MySQL, SQL 서버에는 없다는 점을 덧붙이세요. 이러한 데이터베이스에서는 여전히 하위 쿼리/CTE가 필요합니다.

-- Snowflake / BigQuery only:
SELECT department, name, salary
FROM employees
QUALIFY ROW_NUMBER() OVER (
  PARTITION BY department ORDER BY salary DESC
) = 1;

HAVING과 윈도 결과 걸러내기를 혼동하지 마세요

지원자는 때때로 순위를 걸러내기 위해 HAVING을 사용하려고 합니다. HAVING은 GROUP BY 집계 후에 그룹을 걸러내며, 여전히 윈도 함수보다 먼저 실행됩니다. 따라서 윈도 열도 참조할 수 없습니다.

  • WHERE → 그룹화와 윈도 처리 전에 행을 걸러냅니다.
  • HAVING → 집계된 그룹을 걸러내며, 여전히 윈도 처리 전에 실행됩니다.
  • 윈도 결과 걸러내기 → 외부 쿼리(또는 QUALIFY)가 필요합니다.

사전 조건과 윈도 조건을 함께 적용하기

윈도 처리 전과 후에 모두 조건을 적용해야 하는 경우가 많습니다. 내부 WHERE에서 일반 행 조건을 적용하여 윈도 함수가 관련 행만 보게 한 다음, 외부 쿼리에서 윈도 결과를 걸러냅니다.

이 예제에서는 먼저 활성 직원으로 범위를 제한한 다음, 그중에서 각 부서의 최고 급여 직원을 선택합니다. WHERE active를 안쪽에 넣으면 순위를 매기는 행이 달라집니다.

WITH ranked AS (
  SELECT department, name, salary,
         ROW_NUMBER() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rn
  FROM employees
  WHERE is_active = true        -- pre-filter before ranking
)
SELECT * FROM ranked
WHERE rn = 1;                   -- post-filter on the window

성능 참고 사항

면접관은 감싸기가 성능을 저하하는지 물어볼 수 있습니다. 보통은 그렇지 않습니다. 최적화기는 하위 쿼리/CTE를 하나의 실행 계획 일부로 처리하고 윈도를 한 번만 계산합니다. 감쌌다는 이유만으로 추가 검사가 발생하지는 않습니다.

다만 일부 엔진에서는 CTE가 최적화 경계(구체화된 상태)가 될 수 있습니다. 따라서 자주 실행되는 경로에서는 파생 테이블이나 QUALIFY가 더 나은 실행 계획을 만들 수 있습니다. 중요하다면 EXPLAIN으로 성능을 분석하세요.

자주 하는 실수

최종 확인 목록입니다:

  • 윈도 함수를 WHERE/HAVING에 절대 넣지 마세요 — 오류가 발생합니다.
  • 항상 파생 테이블에 별칭을 지정하세요. FROM에 이름 없는 하위 쿼리를 사용하면 거부됩니다.
  • 질문에서 요구하는 동률 처리 방식에 맞춰 순위 함수를 선택하세요.
  • 지원되는 곳에서만 QUALIFY를 사용하고, 그렇지 않으면 CTE/하위 쿼리 감싸기로 대체하세요.

빠른 확인

윈도 함수를 걸러내려면 왜 감싸기가 필요한가요?

복습: 윈도 결과 걸러내기

순위 윈도 함수의 전체 흐름을 마무리했습니다:

  • 윈도 함수는 WHERE/GROUP BY/HAVING 다음에 실행되므로, 이 절들에서는 윈도 함수를 조건으로 사용할 수 없습니다.
  • 윈도를 하위 쿼리 또는 CTE로 감싸고(항상 별칭을 지정해야 합니다), 외부 쿼리에서 결과를 걸러내세요.
  • 이 방식은 그룹별 상위 N개, 키별 최신 행, 누적 합계 기준값을 구하는 데 사용됩니다.
  • QUALIFY는 스노플레이크/BigQuery에서만 사용할 수 있는 편리한 비표준 지름길입니다.

이제 면접관이 가장 자주 확인하는 순위 도구를 모두 갖추었습니다.

자주 묻는 질문

“윈도 결과로 필터링하기” 강의는 무료인가요?

네 — “윈도 결과로 필터링하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Coding Interview Prep 강의 전체를 잠금 해제할 수 있습니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

“윈도 결과로 필터링하기”에서 뭘 배우나요?

윈도 함수를 하위 쿼리나 CTE로 감싸야 필터링할 수 있는 이유를 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Coding Interview Prep을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Coding Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“윈도 결과로 필터링하기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Coding Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Coding Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. OVER, PARTITION BY와 ORDER BY
  2. ROW_NUMBER로 고유한 순서 부여하기
  3. 동점 상황에서 RANK와 DENSE_RANK 비교하기
  4. 윈도 결과로 필터링하기
← Coding Interview Prep(으)로 돌아가기