오늘은 윈도우 함수를 정리해보려고 합니다 :)
윈도우 함수란?
행과 행간의 관계를 쉽게 정의하기 위해 만든 함수
[Index]
1. 윈도우 함수란?
2. 집계 함수 [SUM, MAX]
3. 순위 [ROW_NUMBER(), RANK(), DENSE_RANK()]
4. 데이터 위치 [LEAD(), LAG()]
1. 윈도우 함수란?
- 행과 행의 관계를 정의하기 위해 사용하는 함수
- 집계 함수(SUM, MAX, MIN ...)를 사용할 때, 윈도우 절을 이용하면 집계 대상이 되는 레코드 범위 지정이 가능하다.
- RDBMS의 행과 행의 관계를 연산하거나 정의하는 것이 어려운 문제를 해결하기 위해 제시된 것이다.
[윈도우 함수 구조]
함수(컬럼명) OVER (PARTITION BY 컬럼명 ORDER BY 컬럼명)
PARTITION BY | 특정 기준에 의해 소그룹으로 나눈다. |
ORDER BY | 특정 항목을 기준으로 정렬한다. |
2. 집계 함수
MAX(컬럼1) OVER (PARTITION BY 컬럼2)
컬럼2별로 컬럼1의 최댓값을 구한다.
예시)
<code>
SELECT customer_id
, order_id
, customer_name
, price
, MAX(price) OVER (PARTIION BY order_id) AS price_max
FROM orders
<result>
customer_id | order_id | customer_name | price | price_max |
1 | 1 | Jenny | 5000 | 5000 |
2 | 2 | Sunny | 8000 | 10000 |
3 | 2 | Amy | 10000 | 10000 |
4 | 4 | Sam | 6000 | 11000 |
5 | 4 | Jack | 11000 | 11000 |
order_id가 1인 행의 price는 5000밖에 없으므로, 최댓값이 5000
order_id가 2인 행의 price는 8000, 10000이므로, 최댓값이 10000
order_id가 4인 행의 price는 6000, 11000이므로, 최댓값이 11000
따라서 order_id가 1인 경우 price_max값이 5000, order_id가 2인 경우 price_max값이 10000, order_id가 4인 경우 price_max값이 11000이다.
SUM(컬럼1) OVER (ORDER BY 컬럼2 PARTITION BY 컬럼3)
컬럼3별로 컬럼1의 누적합을 구하고, 컬럼2를 기준으로 오름차순 정렬된다.
예시)
<code>
SELECT customer_id
, order_id
, customer_name
, price
, SUM(price) OVER (ORDER BY price PARTITION BY order_id) AS CumSum
FROM orders
<result>
customer_id | order_id | customer_name | price | CumSum |
1 | 1 | Jenny | 5000 | 5000 |
2 | 2 | Sunny | 8000 | 8000 |
3 | 2 | Amy | 10000 | 18000 |
4 | 4 | Sam | 6000 | 6000 |
5 | 4 | Jack | 11000 | 17000 |
customer_id가 3인 행의 CumSum값은 8000+10000=18000이고,
customer_id가 5인 행의 CumSum값은 6000+11000=17000이다.
order_id별로 누적합을 구한다.
3. 순위
RANK()
ORDER BY를 포함한 쿼리문에서 특정 컬럼의 순위를 구하는 함수, 동일한 값에 대해
같은 순위를 부여하고 중간 순위를 비운다 → 1,1,3,4,5
예시)
<code>
SELECT score
, RANK() OVER (ORDER BY score DESC) 'rank'
FROM exam
<result>
score | rank |
94 | 1 |
94 | 1 |
88 | 3 |
82 | 4 |
77 | 5 |
77 | 5 |
77 | 5 |
70 | 8 |
score가 94인 행이 2개 존재하므로, 중간 순위인 2위를 비워놓고 다음 순위는 3위이다.
score가 77인 행이 3개 존재하므로, 중간 순위인 6위, 7위를 비워놓고 다음 순위는 8위이다.
DENSE_RANK()
RANK와 작동법을 동일하나, 동일한 값에 대해 같은 순위를 부여하고 중간 순위를 비우지 않는다. → 1,1,2,3,4
예시)
<code>
SELECT score
, DENSE_RANK() OVER (ORDER BY score) AS 'dense_rank'
FROM exam
<result>
score | dense_rank |
94 | 1 |
94 | 1 |
88 | 2 |
82 | 3 |
77 | 4 |
77 | 4 |
77 | 4 |
70 | 5 |
score가 94인 행이 2개 존재하지만, 중간 순위인 2위를 비우지 않고 다음 순위는 2위이다.
score가 77인 행이 3개 존재하지만, 중간 순위인 5위, 6위를 비우지 않고 다음 순위는 5위이다.
ROW_NUMBER()
RANK, DENSE_RANK는 동일한 값에 동일 순위를 부여하지만,
ROW_NUMBER는 동일한 값이어도 고유한 순위를 부여한다. → 1, 2, 3, 4, 5
예시)
<code>
SELECT score
, ROW_NUMBER() OVER (ORDER BY score) AS 'row_number'
FROM exam
<result>
score | row_number |
94 | 1 |
94 | 2 |
88 | 3 |
82 | 4 |
77 | 5 |
77 | 6 |
77 | 7 |
70 | 8 |
ROW_NUMBER()은 동일한 값이 있어도 동일한 순위를 부여하지 않고, 고유의 순위를 부여한다.
4. 데이터 위치
LEAD()
LEAD(컬럼명, 칸 수, 디폴트) OVER (PARTITION BY 컬럼명 ORDER BY 컬럼명)
지정한 칸 수 이후 행의 값을 가져온다.
칸 수의 default값은 1이고, 세번째 인자는 가져올 행이 없을 경우의 값을 지정해주는 것이다.
예시)
<code>
SELECT customer_id
, order_id
, customer_name
, price
, LEAD(price) OVER (ORDER BY customer_id) AS price_lead
FROM orders
<result>
customer_id | order_id | customer_name | price | price_lead |
1 | 1 | Jenny | 5000 | 8000 |
2 | 2 | Sunny | 8000 | 10000 |
3 | 2 | Amy | 10000 | 6000 |
4 | 4 | Sam | 6000 | 11000 |
5 | 4 | Jack | 11000 | NULL |
customer_id가 1인 행을 설명하자면, 다음 행인 customer_id가 2인 행의 price값 8000을 가져온다.
LAG()
LAG(컬럼명, 칸 수, 디폴트) OVER (PARTITION BY 컬럼명 ORDERY BY 컬럼명)
지정한 칸 수 이전 행의 값을 가져온다.
칸 수의 default값은 1이고, 세번째 인자는 가져올 행이 없을 경우의 값을 지정해주는 것이다.
예시)
<code>
SELECT customer_id
, order_id
, customer_name
, price
, LAG(price, 2) OVER (ORDER BY customer_id) AS price_lag2
FROM orders
<result>
customer_id | order_id | customer_name | price | price_lag2 |
1 | 1 | Jenny | 5000 | NULL |
2 | 2 | Sunny | 8000 | NULL |
3 | 2 | Amy | 10000 | 5000 |
4 | 4 | Sam | 6000 | 8000 |
5 | 4 | Jack | 11000 | 10000 |
customer_id가 1인 행을 설명하자면, 2칸 이전 행은 존재하지 않기 때문에, null값을 가져온다.
customer_id가 4인 행을 설명하자면, 2칸 이전 행인 customer_id가 2인 행의 price값 8000을 가져온다.
본 게시글은 인프런의 '[백문이불여일타] 데이터 분석을 위한 고급 SQL' 강의를 듣고 저의 생각을 바탕으로 강의 내용을 재구성하여 작성한 것입니다. 😀
'📖 STUDY > SQL' 카테고리의 다른 글
[EP.01] 데이터베이스 (2) | 2023.10.11 |
---|---|
[EP.00] SQL 공부 다시 시작하기 (2) | 2023.10.11 |
[SQL] 서브쿼리 (0) | 2022.03.31 |
[SQL] INSERT, UPDATE, DELETE (0) | 2022.03.26 |
[SQL] UNION, UNION ALL (0) | 2022.03.15 |