Language/SQL

[SQL]윈도우 함수

eunzae 2022. 12. 16. 15:16

윈도우 함수

  - 순위, 집계 등 행과 행 사이에 관계를 정의하는 함수

  - OVER 구문을 필수로 함

 

SELECT WINDOW_FUNCTION(ARGUMENTS) OVER ([PARTITION BY 컬럼] [ORDER BY절] [WINDOWING절])
FROM 테이블명
;
구조 설명
ARGUMENTS 윈도우 함수에 따라서 필요한 인수
PARTITION BY 전체 집합에 대해 소그룹으로 나누는 기준
ORDER BY 소그룹에 대한 정렬 기준
WINDOWING 행에 대한 범위 기준
구조 설명
ROWS 물리적 단위로 행의 집합을 지정
UNBOUNDED PRECEDING 윈도우의 시작 위치가 첫번째 행
UNBOUNDED FOLLOWING 윈도우의 마지막 위치가 마지막 행
CURRENT ROW 윈도우의 시작 위치가 현재 행

 

 

 

순위함수

RANK() OVER ([PARTITION BY 컬럼] [ORDER BY절] [WINDOWING절])

   - RANK: 동일한 값에는 동일한 순위를 부여

   - DENSE_RANK: RANK와 같이 같은 값에는 같은 순위를 부여하나, 한 건으로 취급

   - ROW_NUMBER: 동일한 값이라도 고유한 순위를 부여

 

 

일반 집계 함수

일반 집계 함수(SUM, AVG, MAX, MIN ...)를  GROUP BY 구문 없이 사용할 수 있다

-- 스칼라 서브쿼리 사용
SELECT
    id, name, score, class_id
    (SELECT AVG(score)
    FROM student b
    WHERE b.class_id = a.class_id) class_score_avg
FROM student a
;

-- 윈도우 함수 사용
SELECT
    id, name, socre, class_id, AVG(score) OVER (PARTITION BY class_id)  class_score_avg
FROM student a
;

 

 

 

그룹 내 행 순서 함수

  - FIRST_VALUE: 가장 먼저 나온 값을 구함

  - LAST_VALUE: 가장 나중에 나온 값을 구함

  - LAG: 이전 X번째 행을 가져옴

  - LEAD: 이후 X번째 행을 가져옴

 

그룹 내 행 순서함수 예시(FIRST_VALUE, LAST_VALUE): 본인 반의 최고점, 최저점 함께 출력

SELECT
    id, name, class_id, score,
    FIRST_VALUE(score) 
    OVER(PARTITION BY class_id ORDER BY score 
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
    AS class_min_score,
    LAST_VALUE(score) 
    OVER(PARTITION BY class_id ORDER BY score 
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
    AS class_max_score
FROM student
;

 

그룹 내 행 순서함수 예시(LAG,LEAD): 본인 번호 앞과 뒤에 해당하는 학생의 이름을 함께 출력

SELECT
    id, name, 
    LAG(name,1) OVER(ORDER BY id) AS pre_name,
    LEAD(name,1) OVER(ORDER BY id) AS post_name
FROM student
;

 

 

 

그룹 내 비율함수

  - RATIO_TO_REPORT: 파티션 내 전체 SUM에 대한 비율을 구함

  - PERCENT_RANK: 파티션 내 순위를 백분율로 구함

  - CUM_DIST: 파티션 내 현재 행보다 작거나 같은 건들의 수 누적 백분율로 구함

  - NTILE: 파티션 내 행들을  N등분한 결과를 구함

 

그룹 내 비율 함수 예시(RATIO_TO_REPORT): 직원 전체 급여의 합 중 각 행이 차지하는 비율을 출력

SELECT
    id, name, salary,
    SUM(salary) OVER() as total_salary
    RATIO_TO_REPORT(salary) OVER() as salary_ratio
FROM employee
;
    
-- Maria DB는 지원 안 됨
SELECT
	id, name, salary,
    SUM(salary) OVER() as total_salary
    (SALARY / SUM(salary) over()) as salary_ratio
FROM employee
;

 

그룹 내 비율 함수 예시(PERCENT_RANK, CUME_DIST)

  - PERCENT_RANK는 순위를 백분율로 나타내며, 제일 높은 순위 행은 0, 가장 낮은 순위 행은 1

  - CUM_DIST는 현재 행보다 같거나 낮은 값들을 가지는 행들의 누적 백분율 값을 나타냄

SELECT
    id, name, salary,
    PERCENT_RANK() OVER(ORDER BY salary DESC) AS percent_rank,
    ROUND(CUME_DIST() OVER(ORDER BY salary DESC), 4) AS CUME_DIST
FROM employee
;

 

그룹 내 비율 함수 예시(NTILE): 급여에 따라 직원들을 세 그룹으로 분류

SELECT
    id, name, salary,
    NTILE(3) OVER(ORDER BY salary DESC) as NTILE
FROM employee
;