[내일배움캠프-사전캠프 04일차] Window Function - RANK, SUM

2025. 6. 12. 15:52·백엔드 부트캠프[사전캠프]/TIL

✅Window Function 의 사례와 기본 구조

  • Window Function 은 각 행의 관계를 정의하기 위한 함수로 그룹 내의 연산을 쉽게 만들어준다.
  • 예를 들어 다음의 경우를 생각해보자
    • 한식 식당 중에서 주문건수가 많은 순으로 순위를 매기고 싶은데?
    • 한식 식당 전체 주문건수 중에서 A 식당이 차지하는 비율을 알고 싶은?
    • 2건 이상 주문을 한 소비자 중에, 처음 주문한 식당과 2번째로 주문한 식당을 같이 조회할 수 있을까?
  • 기본 SQL 구조로 해결하기 위해서는 복잡하게 Subquery 문을 이용하거나, 여러 번의 연산을 수행해줘야 하지만, 자체적으로 제공해주는 기능을 이용하면 조금 더 편리하다.

 

Window Function 의 기본 구조

window_function(argument) over (partition by 그룹 기준 컬럼 order by 정렬 기준)
  • window_function : 기능 명을 사용. (sum, avg 와 같이 기능명이 있다)
  • argument : 함수에 따라 작성하거나 생략
  • partition by : 그룹을 나누기 위한 기준. group by 절과 유사하다고 생각하면 된다.
  • order by : window function 을 적용할 때 정렬 할 컬럼 기준

 

 

Rank - N 번째까지의 대상을 조회하고 싶을 때

  • Rank 는 이름에서 유추할 수 있듯이 ‘특정 기준으로 순위를 매겨주는’ 기능이다.
  • 예를 들어, 주문 건수별 순위 매기기, 결제 시간이 빠른 순으로 순위 매기기 등이 가능하다.

[실습] 음식 타입별로 주문 건수가 가장 많은 상점 3개씩 조회하기

음식 타입별, 음식점별 주문 건수 집계하기

select cuisine_type, 
	   restaurant_name, 
	   count(*) as cnt_order
from food_orders
group by 1, 2

 

 

Rank 함수 적용하기

select cuisine_type, restaurant_name, cnt_order,
	   rank() over(partition by cuisine_type order by cnt_order desc) as ranking
from (
    select cuisine_type, 
           restaurant_name, 
           count(*) as cnt_order
    from food_orders
    group by 1, 2
) a;

 

 

3위까지 조회하고, 음식 타입별, 순위별로 정렬하기

select cuisine_type, restaurant_name, cnt_order, ranking
from (
	select cuisine_type, restaurant_name, cnt_order,
		   rank() over(partition by cuisine_type order by cnt_order desc) as ranking
	from (
	select cuisine_type, 
		   restaurant_name, 
		   count(*) as cnt_order
	from food_orders
	group by 1, 2
	) a
) b
where ranking <= 3;

 

 

 

Sum - 전체에서 차지하는 비율, 누적합을 구할 때

  • - Sum 은 앞서 배운 합계를 구하는 기능과 동일하다.
  • - 다만, 누적합이 필요하거나 카테고리별 합계컬럼와 원본 컬럼을 함께 이용할 때 유용하게 사용할 수 있니다.

[실습] 각 음식점의 주문건이 해당 음식 타입에서 차지하는 비율을 구하고, 주문건이 낮은 순으로 정렬했을 때 누적 합 구하기

음식 타입별, 음식점별 주문 건수 집계하기

select cuisine_type, 
	   restaurant_name, 
	   count(*) as cnt_order
from food_orders
group by 1, 2

 

 

카테고리별 합, 카테고리별 누적합 구하기

select cuisine_type, 
	   restaurant_name, 
	   cnt_order,
       sum(cnt_order) over (partition by cuisine_type) sum_cuisine,
       sum(cnt_order) over (partition by cuisine_type order by cnt_order) cum_cuisine
from (
	select cuisine_type, 
		   restaurant_name, 
		   count(*) as cnt_order
	from food_orders
	group by 1, 2
) a
order by cuisine_type, cnt_order;

 

 

누적합 고쳐보기

강의 자료엔 코드가 제대로 포함되지 않아 수정하여 작성

위 정답에선 cnt_order 가 동일한 값을 일괄로 더해 sum_cuisine, cum_cuisine으로 출력되는 문제가 있다.

문제 상황 이해   

이 상황은 SQL에서 `WINDOW` 함수(`SUM` 등)를 사용할 때, `SUM`으로 동일한 `cnt_order` 값을 가진 여러 행이 있을 경우, SQL 엔진은 이 값을 한꺼번에 더하는 현상이 발생한다. cnt_order의 순서를 결정할 명확한 기준이 없으므로 발생한 문제이다.

 

 

해결 방법

이 문제를 해결하려면 `ORDER BY` 절에 `cnt_order` 외에 추가적인 열에 순서를 부여할 수 있는 `restaurant_name`을 포함시켜야 한다. 이렇게 하면 동일한 `cnt_order` 값을 가진 행들이 명확하게 순서가 정해져 누적합이 정상적으로 처리된다.

 

누적합을 순서대로 표기하기 위해 order by에 restaurant_name 을 추가해준다.

select cuisine_type, 
	   restaurant_name, 
	   cnt_order,
       sum(cnt_order) over (partition by cuisine_type) sum_cuisine,
       sum(cnt_order) over (partition by cuisine_type order by cnt_order, restaurant_name) cum_cuisine
from (
	select cuisine_type, 
		   restaurant_name, 
		   count(*) as cnt_order
	from food_orders
	group by 1, 2
) a
order by cuisine_type, cnt_order, restaurant_name;

 

 

 

 

'백엔드 부트캠프[사전캠프]/TIL' 카테고리의 다른 글
  • [내일배움캠프-사전캠프 06일차] Web 2주차
  • [내일배움캠프-사전캠프 05일차] Web 1주 차
  • [내일배움캠프-사전캠프 04일차] SQL로 Pivot Table 만들어보기
  • [내일배움캠프-사전캠프 04일차] IFNULL vs COALESCE
s_y_130
s_y_130
  • s_y_130
    About SY
    s_y_130
  • 전체
    오늘
    어제
    • 분류 전체보기 (436) N
      • JAVA (54)
        • 더 자바 8 (0)
        • JAVA (41)
        • JAVA (JVM) (13)
      • Computer Science (86)
        • CS Basic (7)
        • OOP (11)
        • Design Pattern (16)
        • Network (8)
        • HTTP (6)
        • WEB (22)
        • OS (16)
      • DataBase (29)
        • DB theory (15)
        • MySQL (14)
        • Redis (0)
      • Collection Framework (1)
        • 구현 (1)
      • Data Structure (14)
        • Linear (9)
        • Non-Linear (5)
      • Algorithm (19)
        • Basic (12)
        • 응용 (2)
        • 완전 탐색(Brute Force) (1)
        • 다익스트라 (1)
        • Algorithm Problem (3)
      • Spring (104)
        • 스프링 핵심 원리 - 기본편 (9)
        • 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 (7)
        • 스프링 MVC 2편 - 백엔드 웹 개발 핵심 기술 (11)
        • 스프링 DB 1편 - 데이터 접근 핵심 원리 (6)
        • 스프링 DB 2편 - 데이터 접근 활용 기술 (10)
        • 스프링 핵심 원리 - 고급편 (13)
        • 스프링 부트 - 핵심 원리와 활용 (9)
        • Spring Security 6.x (2)
        • Spring Batch (2)
        • Spring Cloud로 개발하는 MSA (1)
        • 재고시스템으로 알아보는 동시성이슈 해결방법 (4)
        • 개념 (27)
        • 테스트 (0)
        • Annotation (1)
        • Error Log (2)
      • TEST (0)
        • 부하 테스트 (0)
        • Practical Testing: 실용적인 테스트.. (0)
      • JPA (40)
        • 자바 ORM 표준 JPA 프로그래밍 (12)
        • 1편- 실전! 스프링 부트와 JPA 활용 (7)
        • 2편- 실전! 스프링 부트와 JPA 활용 (4)
        • 실전! 스프링 데이터 JPA (6)
        • 실전! Querydsl (6)
        • 개념 (5)
      • 백엔드 부트캠프[사전캠프] (35)
        • TIL (12)
        • 문제풀이 (23)
      • 백엔드 부트캠프 (5) N
        • Calculator (3)
        • Kiosk (2) N
      • Open Source (0)
      • Book Study (1)
        • Morden Java in Action (1)
        • Real MySQL 8.0 Vol.1 (0)
        • TDD : By Example (0)
      • AWS (0)
        • EC2 (0)
      • git (2)
      • AI (22)
        • Machine Learning (17)
        • Deep Learning (0)
        • TensorFlow (1)
        • PyTorch (1)
        • YOLO (1)
        • Data Analysis (0)
        • Ai code Error (1)
        • Numpy (1)
      • MY (0)
      • WEB (15)
        • Django (3)
        • WEB 개념 (1)
        • React (1)
        • Maven (10)
      • Python (6)
      • 기초수학 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
s_y_130
[내일배움캠프-사전캠프 04일차] Window Function - RANK, SUM
상단으로

티스토리툴바