오늘부터 메타코드M AI 교육 플랫폼에서 무료로 강의를 수강하고,
블로그에 공부 후기를 작성하는 메타코드 서포터즈 5기를 신청하게 되었다.
메타코드는 인공지능, 데이터분석과 같은 최근 중요도가 높은 분야에 대해서
현직자 분들이나 KAIST, 서울대 박사 분들께서 직접 강의를 찍어주시고 계신다.
따라서, 실무에서 쓰이는 스킬들을 핵심만 짚어서 학습할 수 있다는 점에서 꼭 추천하고 싶다.
또한, 메타코드 회원 가입을 하면 12,000 포인트를 지급해주는데,
이 포인트를 이용해서 상시로 진행하는 이벤트에 응모할 수도 있으니 한 번 도전해보시길!
신규 개설된 유료 강의를 선착순으로 무료로 들을 수 있는 기회도 있으니 놓치지 말자!
1. Window
WINDOW 함수는 SELECT 구문에서 사용되며 분석 구간을 변동시키는 역할을 한다.
즉, 행과 행 간의 관계를 쉽게 정의하는 데 사용되며, 흔히 분석 함수 혹은 순위 함수로도 알려져 있다.
윈도우 함수는 기존에 사용하던 집계 함수도 있고, 새로이 윈도우 함수 전용으로 만들어진 기능도 있다.
윈도우 함수는 다른 함수와 달리 중첩해서 사용은 못하지만, 서브쿼리에는 사용할 수 있다.
다음은 WINDOW FUNCTION의 문법 구조이다.
SELECT WINDOW_FUNCTION (ARGUMENTS) OVER
( [PARTITION BY 컬럼] [ORDER BY 컬럼] [WINDOWING 절] )
FROM [테이블명];
윈도우 함수에는 OVER 문구가 키워드로 필수 포함된다.
문법 구조의 요소 하나씩 살펴보자.
- ARGUMENTS(인수): 함수에 따라 0~N개 인수가 지정될 수 있다.
- PARTITION BY: GROUP BY와 비슷한 역할로, 그룹별로 누적 합계를 구할 수 있다.
PARTITION BY 함수와 GROUP BY의 차이는 무엇일까?
GROUP BY는 그룹 집계 결과를 출력하는 반면, PARTITION BY 함수는 본래의 TABLE 그대로 출력한다.
따라서, PARTITON BY는 생략이 가능하지만, ORDER BY를 생략하면 누적 합 계산 시 계산되지 않는다.
다음 예시를 통해 쉽게 이해해보자.
1. SELECT 구문
SELECT customernumber, paymentdate, amount:
이 부분은 결과 집합에 포함할 열을 지정한다.
'customernumber': 고객의 고유 번호, 'paymentdate': 결제가 이루어진 날짜, 'amount': 결제 금액이다.
2. SUM 절
SUM(amount) OVER(PARTITION BY customernumber ORDER BY paymentdate) AS total_amount:
다음으로 SUM 절을 통해 각 고객의 결제 금액을 누적합을 계산한다.
하나하나 나눠서 파악해보자.
'sum(amount)' OVER'는 윈도우 함수로, 지정된 윈도우 또는 파티션 내에서 누적합을 계산한다.
'PARTITION BY customernumber'는 고객별로 데이터를 분할하여 각 고객의 결제 금액을 별도로 누적한다.
'ORDER BY paymentdate'는 결제 날짜 순서대로 누적합을 계산한다.
'AS total_amount'는 계산된 누적합에 대해 'total_amount'라는 별칭을 부여한다.
이러한 과정을 통해 위의 출력 결과가 도출되는 것이다.
윈도우 함수를 사용하여 데이터 내에서 그룹별로 누적 계산을 수행하는 데 매우 유용하다.
1.1 LAG/LEAD 함수
LAG/LEAD 함수는 파티션별 윈도우에서 이전/이후 행의 값을 가져오는 함수이다.
SQL SERVER에서는 지원하지 않는다는 특징이 있다.
예시를 통해 한 번에 이해해보자.
이 SQL 쿼리는 'orders' 테이블에서 주문 번호, 고객 번호, 주문 날짜,
그리고 각 고객 별로 이전 주문 날짜와 다음 주문 날짜를 조회하는 쿼리다.
여기서, 첫 번째 주문의 경우 이전 주문이 없기 때문에 'NULL'
마찬가지로 'next_order_date'도 마지막 주문의 다음 주문이 없기 때문에 'NULL'
각 부분에 대해 설명해보면,
1. SELECT 문:
SELECT orderNumber, customerNumber, orderDate:
먼저, 결과 집합에 포함할 열을 지정한다. (주문 번호, 고객 번호, 주문 날짜)
2. LAG 문:
LAG(orderDate) OVER (PARTITION BY customerNumber ORDER BY orderDate) AS prev_order_date;
'LAG(orderDate) OVER': 윈도우 함수로, 지정된 윈도우 또는 파티션 내에서 이전 주문 날짜를 반환
'PARTITON BY customerNumber': 고객별로 데이터를 분할하여 각 고객의 주문을 별도로 계산
'ORDER BY orderDate': 주문 날짜 순서대로 정렬
'AS prev_order_date': 계산된 이전 주문 날짜에 대해 'prev_order_date'라는 별칭을 부여
3. LEAD 문:
LEAD(orderDate) OVER (PARTITION BY customerNumber ORDER BY orderDate) AS next_order_date:
'LEAD(orderDate) OVER': 윈도우 함수로, 지정된 윈도우 또는 파티션 내에서 이후 주문 날짜를 반환
'PARTITION BY customerNumber': 고객별로 데이터를 분할하여 각 고객의 주문을 별도로 계산
'ORDER BY orderDate': 주문 날짜 순서대로 정렬
'AS next_order_date': 계산된 이후 주문 날짜에 대해 'next_order_date'라는 별칭을 부여
1.2 순위 함수
만약, 그룹 내 순위(RANK)를 추출하려면 어떻게 해야할까?
1. RANK
RANK 함수는 순위를 구하는 함수로, 특정 범위 (PARTITION) 내에서 순위를 구할 수 있고,
전체 데이터에 대한 순위를 구할 수도 있다. 동일한 값에 대해서는 동일한 순위를 부여하게 된다.
2. DENSE_RANK
RANK와 유사하지만, 동일한 순위를 하나의 건수로 취급한다.
ex) RANK는 1, 2, 3순위로 표기하지만, DENSE_RANK는 1, 1, 3 순위를 부여
3. ROW_NUMBER
RANK, DENSE_RANK가 동일한 값에 대해서는 동일한 순위를 부여하는데 반해,
ROW_NUMBER는 동일한 값이라도 고유한 순위를 부여한다.
예시 코드를 살펴보자.
SELECT customername, creditlimit,
ROW_NUMBER() OVER ( ORDER BY creditlimit ASC) AS row_number_,
RANK() OVER ( ORDER BY creditlimit ASC) AS rank_,
DENSE_RANK() OVER ( ORDER BY creditlimit ASC) AS dense_rank_
FROM customers
ORDER BY creditlimit ASC;
이 SQL 쿼리는 'customer' 테이블에서 고객 이름, 신용 한도, 그리고 신용 한도에 따라 세 가지 순위 번호('row_number_', rank_', 'dense_rank_'를 조회한다.
각 부분에 대해 설명해보면,
1. SELECT 문:
SELECT customername, creditlimit,
먼저, 결과 집합에 포함할 열을 지정한다. (고객 이름, 신용 한도)
2. ROW_NUMBER() 문
ROW_NUMBER() OVER ( ORDER BY creditlimit ASC) AS row_number_,
'ROW_NUMBER() OVER': 결과 집합의 각 행에 대해 고유한 순번을 부여
'OVER (ORDER BY creditlimit ASC)': 신용 한도를 오름차순 정렬하여 순번을 부여
'AS row_number_: 계산된 순번에 대해 'row_number_'라는 별칭을 부여
3. RANK() 문
RANK() OVER ( ORDER BY creditlimit ASC) AS rank_,
' RANK() OVER': 동일한 값이 있을 경우 같은 순위 부여, 다음 순위는 그 값의 개수만큼 건너뜀
'OVER (ORDER BY creditlimit ASC)': 신용 한도를 기준으로 오름차순 정렬하여 순위 부여
'AS rank_': 계산된 순위에 대해 'rank_'라는 별칭을 부여
4. DENSE_RANK() 문
DENSE_RANK() OVER ( ORDER BY creditlimit ASC) AS dense_rank_,
'DENSE_RANK() OVER': 동일한 값이 있을 경우 같은 순위를 부여하지만, 다음 순위는 건너뛰지 않음
'OVER (ORDER BY creditlimit ASC)': 신용 한도를 기준으로 오름차순 정렬하여 순위 부여
'AS dense_rank_': 계산된 순위에 대해 'dense_rank_'라는 별칭을 부여
customername | creditlimit | row_number_ | rank_ | dense_rank_ |
Alice | 5000 | 1 | 1 | 1 |
Bob | 5000 | 2 | 1 | 1 |
Charlie | 7000 | 3 | 3 | 2 |
David | 7000 | 4 | 3 | 2 |
Eve | 10000 | 5 | 5 | 3 |
차이가 정리 됐을 것이라 생각한다.
또한, First_value(), Last_value()를 사용하면,
테이블 내의 가장 첫 번째 row와 마지막 row를 조회할 수 있다.
따라서, 앞서 소개한 RANK를 통해 순위를 확인할 수도 있지만,
조회하고 싶은 순위가 1등과 마지막인 경우에는 유용하게 활용할 수 있겠다.
1.3 WINDOW FRAME
다음으로, 프레임 내에서도 범위를 설정 할 수 있다.
UNBOUNDED PRECEDING / CURRENT ROW / UNBOUNDED FOLLOWING
위 세 가지를 적절히 조합하면 윈도우 프레임 내에서도 선택 범위를 정할 수 있다.
기준행은 current row가 되고, window function은 "행의 길이"를 보존하기 때문에 한줄 한줄 모든 행이 current row가 된다.
가령, 다음과 같은 테이블이 있다고 하자. current row는 24년 7월 16일이다.
일자 | 매출 |
2024-07-14 | 10000 |
2024-07-15 | 10000 |
2024-07-16 | 20000 |
2024-07-17 | 30000 |
1. ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
해석하자면, 이전에 제한이 없다는 뜻이며, 테이블의 범위는 다음과 같다.
일자 | 매출 |
2024-07-14 | 10000 |
2024-07-15 | 10000 |
2024-07-16 | 20000 |
2. ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
해석해보면 다음에 제한이 없다는 뜻이겠지?
일자 | 매출 |
2024-07-16 | 20000 |
2024-07-17 | 30000 |
3. ROWS BETWEEN 1 PRECIDING AND 1 FOLLOWING
현재행을 기준으로 범위를 지정할 수도 있다. 한개 이전, 그리고 한개 이후
일자 | 매출 |
2024-07-15 | 10000 |
2024-07-16 | 20000 |
2024-07-17 | 30000 |
윈도우 프레임을 이용하면 퍼널 분석 로직을 구현할 수도 있다.
다음에 실습해보는 것으로!
오늘 강의 후기
드디어 SQL에서 가장 중요한 개념 중 하나인 WINDOW 함수를 배웠는데,
뭔가 기존에 책으로 공부하던 것보다 핵심만 딱 요약해서 설명해주시는 느낌이라서
공부하는 데도 지루하지 않고 조금 더 내용적으로도 잘 이해되는 것 같다.
앞으로 강의와 실습을 바탕으로 SQL 마스터 해보자 ,,
해당 강의를 들을 지 말지 고민말고 한 번 들어보시길!
이상훈 강사님의 데이터분석가 입문 필수 SQL 부트캠프
데이터 분석가 공부를 시작하려는 학생들에게 강추합니다!
* 서포터즈 지원을 받아 작성하였습니다
'Portfolio > 메타코드M 서포터즈 5기' 카테고리의 다른 글
[메타코드 강의 후기] 서브쿼리 & CTE (0) | 2024.07.21 |
---|---|
[메타코드 강의 후기] Having & JOIN 구문 (0) | 2024.07.08 |
[메타코드 강의 후기] SQL 부트캠프 | WHERE & ORDER BY & GROUP BY (0) | 2024.06.30 |
[메타코드 강의 후기] SQL 부트캠프 | DataType & Table 생성 (4) | 2024.06.23 |
[메타코드 강의 후기] SQL 부트캠프 | 데이터베이스란? (1) | 2024.06.16 |