1. ROW_NUMBER()
ROW_NUMBER() 함수는 각 행에 고유한 순번을 부여하는 윈도우 함수로, 데이터 정렬, 순위 매기기, 페이징 처리 등에 사용된다.
정렬 기준이 필요하므로 ORDER BY와 필수로 사용되며 그룹별로 순번을 따로 지정하고 싶은 경우 PARTITION BY를 선택적으로 사용할 수 있다.
sql
SELECT
EMPNO, ENAME, SAL,
ROW_NUMBER() OVER (ORDER BY SAL DESC)
FROM
EMP
2. OVER()
OVER()는 윈도우 함수를 사용할 때 필수 절로, 집합화된 row들의 정렬 순서를 지정하는 데 사용된다.
OVER()를 사용할 때는 ORDER BY 절을 사용하여 정렬 순서를 지정할 수 있다.
ORDER BY 절은 출력되는 로우의 순서와 일치하지 않아도 된다.
sql
SELECT
DEPTNAME,
EMPNO,
SAL,
RANK() OVER (PARTITION BY DEPTNAME ORDER BY SAL DESC)
FROM
EMP
3. PARTITION BY
PARTITION BY는 데이터를 그룹으로 분할하여 계산하는 데 사용된다. 마치 GROUP BY처럼 동작하지만, 집계하지 않고 원본 데이터를 유지하면서 그룹 내에서만 순번이나 계산을 적용할 수 있다.
즉, GROUP BY는 그룹화된 데이터 묶음을 집계함수를 이용하여 필요한 값을 계산하고, 이를 하나의 행으로 집약시키지만, PARTITION BY는 계산된 값을 그룹화된 데이터의 각각 행에 모두 별도의 컬럼으로 추가한다.
예시 1. GROUP BY - 부서 별 평균 급여
sql
SELECT
DEPTNO,
AVG(SAL) AS AVG_SAL
FROM
EMP
GROUP BY
DEPTNO
- DEPTNO가 10, 20, 30이면 3행만 출력됨 (요약된 값)
예시 2. PARTITION BY - 부서별 평균 급여를 모든 행에 표시
sql
SELECT
EMPNO, ENAME, DEPTNO, SAL,
AVG(SAL) OVER(PARTITION BY DEPTNO) AS AVG_SAL
FROM
EMP
4. Trouble Shoot
실무 중 입금 내역을 조회하는 화면에서 약정금이 중복으로 표시되고 집계되는 문제가 있었다.

- 하나의 약정금에 대해 입금이 여러 차례 나눠서 이루어지는 경우가 있다.
- 이 경우 입금이 2번, 3번 나뉘어져 있다면, 같은 약정금이 2번, 3번 반복해서 조회되는 상황이 발생한다.
- 이로 인해 소계, 총합 계산 시에도 약정금이 실제보다 더 크게 집계되는 오류가 발생한다.
즉, 회차별로 한 번만 보여야 할 약정금이 입금 횟수만큼 반복되어 나오는 문제였다.
동일 회차의 입금 행 중 첫 번째 행만 약정금을 보여주고, 나머지는 0으로 처리하기 위해 Sheet 렌더링 과정에서 셀 병합(Merge) 처리 하려 했지만, 소계 열 생성 내부 메서드와 같이 동작하지 않았다.
또한, 조회 후 Js에서 후처리하는 방법으로 동일 회차의 약정금을 Merge 처리하도록 작성하였다. 시간 복잡도를 계산했을 때 O(n)이 걸림에도 내부적으로 DOM을 조작과 렌더링 관련 오버헤드 때문에 브라우저 성능 저하가 심하여 정상적으로 동작하지 않았다.
앞서 해결 방법들이 잘못됐다 생각이 들었고, 조회 SQL 단계에서 해결하는 것이 단순히 시각적으로 보정하는 것보다 데이터 자체를 논리적으로 통제할 수 있을 것이라 생각했고 다음과 같이 처리했다.
sql
SELECT
입금자, 품목, 구분, 회차, 입금액, 입금일, ...
CASE
WHEN ROW_NUMBER() OVER (
PARTITION BY 입금자, 품목, 구분, 회차, ...
ORDER BY 입금액 DESC, 입금일, ... ASC
) = 1 THEN 약정금
ELSE 0
END AS 약정금
FROM 입금내역
...

'DataBase' 카테고리의 다른 글
| [Database] Index, 인덱스란? (구조, 종류, 동작 원리, 장단점 및 주의 사항) (1) | 2025.04.17 |
|---|---|
| [Database] PL/SQL 이란? Procedure와 Java 프로그래밍의 차이와 생각 (0) | 2025.04.08 |
| [Database] Spring Boot에서 MongoDB Atlas 연결하기 (0) | 2025.02.11 |
| [Database] 채팅 시스템 NoSQL 특성 및 비교 분석(CAP, PACELC) (1) | 2025.02.07 |