ROW_NUMBER 함수란?
- 각 PARTITION 내에서 ORDER BY절에 의해 정렬된 순서를 기준으로 고유한 값을 반환하는 함수입니다.
- 윈도우 함수(Window Funtion)로 그룹 내 순위 함수입니다.
문법
ROW_NUMBER() OVER(PARTITION BY [그룹핑할 컬럼] ORDER BY [정렬할 컬럼])
- PARTITION BY는 선택, ORDER BY는 필수
공부하게 된 계기
구조
이번 프로젝트에서 point 라는 도메인에 유저들이 포인트가 지급되면 하나씩 쌓이는 구조이며,
totalPoint에 최근에 적립된 totalPoint에서 더해져 DB에 적재가 되는 구조입니다.
@Getter
@Setter
@Entity
public class Point extends DateTime {
/**
* 사용자계정
*/
@NotNull
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private User user;
/**
* 적립금
*/
@NotNull
private Integer point;
/**
* 총잔액 적립금
*/
@NotNull
private Integer totalPoint;
}
DB
위에서 말 했듯이 user_id 가 1 인 회원이 500 포인트가 적립되어 totalPoint에 500포인트 쌓였고 다음에 200포인트가 지급되어서 700포인트가 되었다.
user_id가 2인 회원도 마찬가지 입니다.
id | point | total_point | user_id |
1 | 500 | 500 | 1 |
2 | 200 | 700 | 1 |
3 | 350 | 350 | 2 |
4 | 350 | 700 | 2 |
문제점
한명의 회원의 최근의 totalPoint를 조회하는 것을 어렵지 않습니다. 예를 들면 아래와 같은 쿼리가 나올 수 있겠네요
SELECT top(1) *
FROM POINT P
WHERE p.id = :userId
ORDER BY P.id DESC
하지만 여러 명의 회원들을 현재 가지고 있는 포인트를 조회하는 것이 매우 어려워 결국은 팀장님께 자문을 구할 수 밖에 없었습니다. ㅠㅠ 팀장님 덕분에 row_nuber over 와 partition By 를 알게되었고 공부하여 적용 시켰습니다.
SELECT
*
FROM
( SELECT
ROW_NUMBER() OVER (PARTITION BY P.USER_ID ORDER BY P.ID DESC) AS ROW_NUM ,
P.USER_ID AS USER_ID ,
P.TOTAL_POINT
FROM
POINT P
) B
WHERE
B.ROW_NUM = 1;
PARTITION BY 로 user_id 기준으로 나눴고 id 내림차순으로 정렬하여 ROW_NUM이 매겨집니다. 아래와 같이요
DB 데이터 적재 상황
id | point | total_point | user_id |
1 | 500 | 500 | 1 |
2 | 200 | 700 | 1 |
3 | 350 | 350 | 2 |
4 | 350 | 700 | 2 |
outSql 제외하고 inSQL조회로 인해 조회된 데이터
SELECT
ROW_NUMBER() OVER (PARTITION BY P.USER_ID ORDER BY P.ID DESC) AS ROW_NUM ,
P.USER_ID AS USER_ID ,
P.TOTAL_POINT
FROM
POINT P
ROW_NUM | id | USER_ID | TOTAL_POINT |
1 | 2 | 1 | 700 |
2 | 1 | 1 | 500 |
1 | 4 | 2 | 350 |
2 | 3 | 2 | 350 |
전체쿼리조회
SELECT
*
FROM
( SELECT
ROW_NUMBER() OVER (PARTITION BY P.USER_ID ORDER BY P.ID DESC) AS ROW_NUM ,
P.USER_ID AS USER_ID ,
P.TOTAL_POINT
FROM
POINT P
) B
WHERE
B.ROW_NUM = 1;
outSQL 의 where 에 row_num 이 1 인 것들만 조회 될 것이니 아래와 같이 정리됩니다.
ROW_NUM | id | USER_ID | TOTAL_POINT |
1 | 2 | 1 | 700 |
1 | 4 | 2 | 350 |
이제는 회원 1, 2 에 대한 totalPoint를 알게 되었습니다.
'데이터베이스 > mssql' 카테고리의 다른 글
[MSSQL] 테이블을 참조하는 FOREIGN KEY 제약 조건을 찾기 (0) | 2023.09.06 |
---|