오라클 SQL을 사용하다 보면 특정 기준값에 가장 가까운 값, 즉 근삿값(近似値, 근사치) 을 찾아야 하는 상황이 종종 발생합니다. 예를 들어 급여 테이블에서 SAL 값이 1200에 가장 가까운 직원을 찾고자 하거나, 제품 테이블에서 가격이 특정 값과 가장 근접한 상품을 찾고 싶은 경우가 있을 수 있죠.
이러한 상황에서 오라클 SQL에서는 ROW_NUMBER 함수 또는 RANK 함수를 이용하여 효과적으로 근삿값을 찾을 수 있습니다. 이 두 함수는 모두 윈도우 함수의 일종으로, 특정 정렬 기준에 따라 순번 또는 순위를 매겨 데이터를 정렬하고 필터링하는 데 매우 유용합니다.
이번 포스팅에서는 오라클 SQL에서 근삿값을 찾는 두 가지 방법에 대해 각각의 특징과 예제를 바탕으로 비교 분석하고, 실무에서의 활용 포인트를 정리해보겠습니다.
📌 목차
- ROW_NUMBER 함수로 근삿값 1건 찾기
- RANK 함수로 근삿값 여러 건 조회하기
- 두 함수의 차이점 및 선택 기준
- 실무에서 자주 쓰는 응용 예제 3가지
- 마무리 요약
1. ROW_NUMBER 함수로 근삿값 1건 찾기
🔧 예제 쿼리
SELECT *
FROM (
SELECT empno,
ename,
sal,
ROW_NUMBER() OVER(ORDER BY ABS(sal - 1200)) AS rn
FROM emp
WHERE job IN ('MANAGER', 'SALESMAN')
)
WHERE rn = 1;
🔍 설명
- ABS(sal - 1200)을 통해 기준값 1200과의 차이의 절댓값을 계산합니다.
- 이 차이를 기준으로 가장 가까운 값부터 정렬됩니다.
- ROW_NUMBER()는 정렬된 결과에 순차적인 번호(1, 2, 3, …) 를 부여합니다.
- WHERE rn = 1을 통해 가장 가까운 1건의 데이터만 조회합니다.
📎 포인트
- ROW_NUMBER는 항상 유일한 순서를 생성하므로, 동일한 근삿값이 있어도 무조건 1건만 조회됩니다.
- 중복된 근삿값이 있을 경우에는 이 방법이 적절하지 않을 수 있습니다.
2. RANK 함수로 근삿값 여러 건 조회하기
🔧 예제 쿼리
SELECT *
FROM (
SELECT empno,
ename,
sal,
RANK() OVER(ORDER BY ABS(sal - 1200)) AS rn
FROM emp
WHERE job IN ('MANAGER', 'SALESMAN')
)
WHERE rn = 1;
🔍 설명
- RANK() 함수는 같은 값에 대해 동일한 순위를 부여합니다.
- 예를 들어 sal 값이 1250인 데이터가 여러 건 있고, 이 값이 기준값(1200)과의 차이가 가장 작다면 모두 1등으로 랭크됩니다.
- WHERE rn = 1 조건을 주면 가장 가까운 값에 해당하는 모든 행이 조회됩니다.
📎 포인트
- RANK는 동일한 근삿값이 여러 건일 때 유리합니다.
- 특정 값과 가장 가까운 모든 데이터를 확인하고 싶을 때 이 방법을 사용하세요.
3. ROW_NUMBER vs RANK: 어떤 걸 언제 써야 할까?
비교 항목 ROW_NUMBER RANK
| 순위 부여 방식 | 고유한 번호(1, 2, 3, …) | 동일한 값은 동일한 순위 부여 (1, 1, 3, …) |
| 근삿값 조회 수 | 1건 | 여러 건 가능 |
| 중복 허용 | ❌ 허용하지 않음 | ✅ 허용함 |
| 실무 활용 예 | 단일값 추출 시 | 동일 근삿값 그룹 추출 시 |
👉 정확히 1건만 필요할 때는 ROW_NUMBER,
👉 중복 포함해서 모두 보고 싶을 땐 RANK를 사용하면 됩니다.
4. 실무 활용 예제 3가지
💼 예제 1. 고객 구매액과 가장 가까운 평균 구매액 찾기
SELECT *
FROM (
SELECT customer_id,
purchase_amount,
ROW_NUMBER() OVER (ORDER BY ABS(purchase_amount - 35000)) AS rn
FROM customer_orders
)
WHERE rn = 1;
👉 평균 구매액이 35,000원일 때, 이 값에 가장 가까운 구매 건을 가진 고객을 찾습니다.
📦 예제 2. 상품 가격이 기준가격에 가장 가까운 상품들 조회
SELECT *
FROM (
SELECT product_id,
product_name,
price,
RANK() OVER (ORDER BY ABS(price - 10000)) AS rank_price
FROM products
)
WHERE rank_price = 1;
👉 기준가격 1만원에 가장 가까운 모든 상품을 확인합니다.
🏢 예제 3. 사원의 근속연수가 기준값과 가까운 1명 찾기
SELECT *
FROM (
SELECT empno,
ename,
hiredate,
ROUND(MONTHS_BETWEEN(SYSDATE, hiredate)/12, 1) AS years_of_service,
ROW_NUMBER() OVER (ORDER BY ABS(MONTHS_BETWEEN(SYSDATE, hiredate) - 60)) AS rn
FROM emp
)
WHERE rn = 1;
👉 근속연수 5년(60개월)과 가장 가까운 사원을 찾을 때 사용할 수 있습니다.
5. 마무리 요약
함수 근삿값 결과 중복 가능성 사용 시기
| ROW_NUMBER() | 1건만 조회 | ❌ | 유일한 근삿값 조회 시 |
| RANK() | 여러 건 가능 | ✅ | 동일한 근삿값 모두 필요할 때 |
정리하자면, 오라클에서 특정 기준에 가장 가까운 데이터를 찾고자 할 때는 ABS 함수로 차이를 계산한 후, ROW_NUMBER 또는 RANK 윈도우 함수를 적용하면 됩니다. 실무에서는 이 테크닉을 잘 활용하면 정확한 데이터 추출과 효율적인 리포트 작성이 가능합니다.
데이터가 중복일 수 있는 상황이라면 반드시 RANK를 고려하세요. 단일 추출이라면 ROW_NUMBER가 깔끔하고 간단한 솔루션입니다.
📚 관련 키워드 태그
#OracleSQL #오라클SQL #ROW_NUMBER #RANK함수 #근삿값 #근사치 #SQL쿼리 #오라클윈도우함수 #오라클데이터분석 #실무SQL #OracleTips #ABS함수 #오라클근사치
'정보' 카테고리의 다른 글
| [Oracle SQL] 초를 분, 시간, 일로 변환하는 방법 완벽 정리 (0) | 2025.05.07 |
|---|---|
| [Oracle SQL] 날짜(Date)에서 시간만 추출하는 2가지 방법: TO_CHAR vs EXTRACT 완벽 정리 (0) | 2025.05.07 |
| [Oracle SQL] 오라클 SYSDATE에서 날짜만 조회하는 2가지 방법 (TRUNC vs TO_CHAR 완전 정리) (0) | 2025.05.07 |
| [Oracle JSON 함수 정복] JSON_ARRAYAGG 함수 완벽 가이드 | 여러 행을 JSON 배열로 묶기 (0) | 2025.05.07 |
| 오라클 JSON_OBJECT 함수 완벽 가이드: 기본 문법부터 고급 옵션까지 (0) | 2025.05.07 |