본문 바로가기
공부/DB

[SQL] ROWNUM = 2

by 미네밍 2021. 1. 15.

쿼리를 짜다보면 ROWNUM 을 쓸 일이 종종 있다.

ROWNUM = 1 의 경우 가장 상위 행을 가져오는 구문이지만, ROWNUM = 2 조건은 아무런 행을 가져오지 않는다.

 

보통 ROWNUM = 2 라는 조건을 사용하고 싶은 경우는, 특별한 기준으로 데이터를 정렬 후 2번째 순위에 있는 데이터를 뽑고 싶을 때 일 것이다. 일단 ROWNUM = 2 과 같은 조건을 사용하고 싶을 땐, 쿼리문을 한번 더 감싸서 바깥 쿼리문에서 조건을 걸어주면 된다.

SELECT

FROM (
      SELECT ROWNUM AS RNUM

           , AAA FROM TBL
       ORDER BY AAA

     ) T

WHERE T.RNUM = 2

다음과 같이 ROWNUM 을 사용하면 원하는 결과를 추출 가능하다.

 

그렇다면 왜 ROWNUM = 2 는 내가 원하는 결과를 추출하지 못하는 것일까?

ROWNUM 은 가상컬럼이다. 결과를 추출하면, 해당 결과에 따라 각 행에 부여되는 숫자이다.

 

보통 ROWNUM 값은 쿼리의 조건절이 처리되고 난 이후, 그리고 정렬 혹은 집계 처리가 수행되기 이전에 부여된다.

WHERE 문이 존재하는 쿼리결과를 반환하기 위해 오라클은 테이블을 한행씩 조회할 것이다(풀 스캔이든 인덱스 스캔이든). 우선 조회하는 첫 번째 행은 항상 ROWNUM = 1 부터 시작한다. 처음 접근한 행이 WHERE 절의 조건에 맞다면 해당 행에 그대로 ROWNUM = 1 이 할당되게 되고, 만약 처음 접근한 행이 WHERE 절의 조건에 맞지 않는 행이라면 해당 행을 건너뛰고 다음 행에 접근한다. 조건에 부합하는 첫번째 행에 최종적으로 ROWNUM = 1 이 할당된다. ROWNUM = 1 이 최종적으로 할당되었다면, 그 이후부터 값이 하나씩 증가되어 2,3... N 까지 숫자가 부여가 된다고 한다.

 

만약 ROWNUM = 2 이 WHERE 조건에 있으면 어떻게 될까? 오라클이 테이블에 접근하여 첫 번째 행을 읽어들였다고 하면, 첫 번째 행은 ROWNUM = 1 이다. 내가 찾는 조건은 ROWNUM = 2 이다. 오라클이 접근한 첫번째 행의 ROWNUM 은 1 이기 때문에, 조건에 부합하지 않는다. 따라서 이 행을 버리고 다음 행에 접근한다. 다음 행 역시 ROWNUM = 1 로 할당된 다른 행이 없기 때문에 ROWNUM 은 1 이 되고, ROWNUM = 2 의 조건에 부합하는 행이 될 수 없어 또 건너뛰게 된다.

 

또한 만약 1~10 위까지 가장 상위 행을 뽑고 싶어 ROWNUM <= 10 과 같은 조건을 붙여주고 싶다고 해도, ROWNUM <= 10 이라는 조건은 원하는 결과를 추출하지 못할 수 있다. 앞서 말했듯 ROWNUM 은 그냥 조건에 맞는 행을 접근한 순서대로 매기는 숫자일 뿐, 우리가 뽑은 결과에 ROWNUM 이 1부터 10 까지 매겨졌다고 해서 해당 데이터가 원하는 대로 정렬이 된 것은 아니기 때문이다. 따라서 정확한 결과를 위해서는 ROWNUM 의 동작원리를 잘 알고 쿼리를 작성해야 한다.

 

참고문서

ROWNUM 의 동작원리

'공부 > DB' 카테고리의 다른 글

[SQL] ROWNUM 적용한 페이징 쿼리  (0) 2021.02.20
쿼리(LEAD)  (0) 2021.02.18
[SQL] Order by 문 변형  (0) 2021.01.15
[중첩루프조인] 오라클 조인 Nested Loop Join  (0) 2019.12.02
오라클 튜닝  (0) 2019.09.22

댓글