콘텐츠로 건너뛰기

SQL QUALIFY – 윈도우 함수로 데이터를 더욱 정밀하게 필터링하기

이번 글에서는 SQL에서 잘 알려진 QUALIFY 문에 대해 알아보겠다. 특히, ROW_NUMBER()RANK() 같은 윈도우 함수와 함께 자주 쓰이는 QUALIFY를 통해 데이터를 더 세밀하게 필터링하는 방법을 살펴보자. 기본 SELECT 문에 아직 익숙하지 않다면, SQL (2) SELECT문 -데이터를 자유자재로 뽑아보자

■ QUALIFY란?

SQL의 QUALIFY 문은 WHEREHAVING처럼 필터링을 할 때 사용하는 문법이다. 다만 WHERE가 행(row) 단위로 조건을 걸고, HAVING이 그룹 단위로 조건을 걸 때, QUALIFY는 윈도우 함수의 결과에 대해 조건을 걸어 필터링하는 데 사용된다. 즉, QUALIFY는 윈도우 함수가 계산된 결과에 대해 추가적으로 조건을 부여할 때 매우 유용하다.

기본 구문은 다음과 같다.

SELECT 컬럼이름 FROM 테이블이름
QUALIFY 윈도우함수 = 조건;

아래와 같은 고객 주문 데이터가 있다고 해보자.

order_idcustomer_idorder_datetotal_amount
11012023-08-01200
21022023-08-05150
31012023-08-10180
41032023-07-20300
51022023-08-15250
61012023-08-20100
71032023-08-25400

이 테이블에서 각 고객별로 가장 최근 주문을 조회하고 싶다면 어떻게 해야 할까? 여기서 ROW_NUMBER()QUALIFY를 함께 사용하여 가장 최신의 주문을 가져올 수 있다.

SELECT DISTINCT order_id, customer_id, order_date, total_amount
FROM Customer_Orders
QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) = 1;
order_idcustomer_idorder_datetotal_amount
61012023-08-20100
51022023-08-15250
71032023-08-25400
  • ROW_NUMBER()는 고객별(customer_id 기준)로 주문 날짜(order_date)에 따라 순번을 매긴다.
  • PARTITION BY customer_id는 고객별로 그룹을 나누는 역할을 하며, 각 그룹에서 ORDER BY order_date DESC를 통해 가장 최신 주문일을 기준으로 순서를 매긴다.
  • QUALIFY ROW_NUMBER() = 1은 각 고객의 최신 주문(순번이 1인 데이터)만 필터링한다.

■ QUALIFY와 RANK() 예시

이제 광고 캠페인 데이터를 관리한다고 가정해보자. 특정 고객이 여러 광고 캠페인에 참여했지만, 각 캠페인 중에서 가장 최신 데이터를 가져오고 싶다면 RANK()를 사용할 수 있다.

campaign_idcustomer_idcampaign_namestart_datestatus
1101Summer Sale2023-06-01active
2102Winter Promo2023-07-15paused
3101Fall Launch2023-08-10active
4103New Year Sale2023-01-05inactive
5102Spring Offer2023-03-25active

고객별로 가장 최신의 캠페인 상태를 조회하고 싶을 때, 다음과 같이 RANK()를 사용하여 조회할 수 있다.

SELECT customer_id, campaign_name, start_date, status
FROM Campaigns
QUALIFY RANK() OVER (PARTITION BY customer_id ORDER BY start_date DESC) = 1;
customer_idcampaign_namestart_datestatus
101Fall Launch200active
102Winter Promo150paused
103New Year Sale300inactive
  • RANK() 함수는 고객별로 캠페인 시작일을 기준으로 순위를 매긴다.
  • PARTITION BY customer_id로 고객별로 그룹을 나누고, ORDER BY start_date DESC로 가장 최근 캠페인이 순위 1이 되도록 정렬한다.
  • QUALIFY RANK() = 1은 각 고객의 가장 최신 캠페인만 필터링하여 반환한다.

■ 실제 비즈니스 사례

1. 고객의 마지막 구매 이력 추출

소비자 행동 분석에서 각 고객의 마지막 구매 이력을 가져오는 것은 매우 중요한 작업이다. 예를 들어, 마케팅 캠페인을 위해 고객의 최신 구매 데이터를 바탕으로 리타겟팅할 때, ROW_NUMBER()QUALIFY를 이용하여 최신 주문만 추출할 수 있다.

SELECT DISTINCT customer_id, purchase_id, purchase_date, total_amount
FROM Purchases
QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY purchase_date DESC) = 1;

2. 이벤트 중복 로그 필터링

이벤트 로그 분석에서 중복된 이벤트나 불필요한 데이터를 걸러내야 할 때가 있다. 예를 들어, 동일한 이벤트에 대한 여러 로그가 기록되었지만, 가장 최근 로그만 남기고 싶다면 다음과 같은 쿼리를 사용할 수 있다.

SELECT DISTINCT event_id, user_id, event_timestamp
FROM Event_Logs
WHERE event_type = 'login'
QUALIFY ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY event_timestamp DESC) = 1;

SQL의 QUALIFY 문은 윈도우 함수와 결합하여 데이터를 정밀하게 필터링하는 강력한 도구이다. ROW_NUMBER()RANK()와 함께 사용하면, 중복된 데이터를 효과적으로 제거하거나, 각 그룹에서 최신 데이터를 빠르게 추출할 수 있다. SELECT DISTINCT에 대해 더 자세히 알고 싶다면, SQL SELECT문 – 중복 제거와 특정 컬럼 제외하기

실제 비즈니스에서 고객 행동 분석이나 이벤트 로그 처리와 같은 작업에 매우 유용하게 적용할 수 있으며, 이를 통해 데이터의 품질을 높이고 분석의 효율성을 극대화할 수 있다.