2021-04-10
오라클 내부에서 각 테이블에 행 번호를 매길 수 있는 방법이 존재한다. 이는 ROWNUM을 이용하는 것인데, 이와 같은 방법을 알아보자.
- 예제
예제는 SEE_INFO라는 이름을 가진 테이블을 사용할 것이며, 테이블 내부의 데이터는 아래와 같다.
- ROWNUM
먼저 기초적인 ROWNUM을 포함하여 전체 TABLE 데이터를 출력해보자. 사용하는 방법은 아래와 같다.
SELECT ROWNUM NUM, SEE_INFO.* FROM SEE_INFO;
SELECT 절에 ROWNUM을 명시해주면 되며, 이후 테이블명.* 과 같이 써주면 된다. FROM 절에 테이블이 이미 명시되어 있다고 SELECT 절에 테이블명 없이 '*'만 사용할 경우 에러가 나는 점도 알아두자.
- ROWNUM 정렬
우선 좀더 명확하게 보기 위해 추가적인 데이터를 삽입하였다.
INSERT INTO SEE_INFO VALUES(22, 'TEST1', 11, 1);
INSERT INTO SEE_INFO VALUES(23, 'TEST2', 12, 2);
INSERT INTO SEE_INFO VALUES(28, 'TEST3', 13, 2);
INSERT INTO SEE_INFO VALUES(26, 'TEST4', 14, 3);
INSERT INTO SEE_INFO VALUES(27, 'TEST5', 15, 4);
ROWNUM이 들어가 있는 경우 ORDER BY 절을 통해 정렬을 수행하면, 그 순서가 뒤죽박죽이 되는데(쿼리에 따라 안 바뀌는 경우도 있음), 이와 같은 경우 어떻게 해결하는지 알아보자.
--나이순으로 정렬
SELECT ROWNUM, SEE_INFO.* FROM SEE_INFO ORDER BY AGE;
결과를 보면 뒤죽박죽으로 ROWNUM이 부여된 것을 확인할 수 있다.
위와 같이 ROWNUM이 뒤죽박죽 되는 이유는 쿼리 문의 진행순서이기 때문이다. FROM - WHERE - (GROUP BY) - SELECT - ORDER BY 순으로 쿼리가 진행된다. 때문에 SELECT이 진행되었을 때 이미 ROWNUM은 매겨진 상태이고 그 상태에서 ORDER BY를 통한 정렬이 발생하니 위와 같은 결과가 나오는 것이다.
해결 방법은 아래와 같다.
--기존의 SEE_INFO 테이블을 먼저 정렬시킴 이후에 ROWNUM을 매김
SELECT ROWNUM, SI1.* FROM(SELECT * FROM SEE_INFO ORDER BY AGE)SI1;
먼저 FROM 절에서 SEE_INFO TABLE을 나이순으로 정렬시킨 뒤 그 이후 값에 ROWNUM을 붙여주는 것이다, 결과를 확인해보면 나이순으로 정렬됨과 동시에 ROWNUM도 나이에 따라 순서대로 부여된 것을 확인할 수 있다.
- ROWNUM 값 추출
그렇다면 특정 ROWNUM 범위에 있는 데이터만 추출하고 싶을때는 어떻게 해야 할까 방법은 아래와 같다. 이것도 앞서 말했듯이 쿼리 문의 진행순서를 파악하면, 어느 정도 감이 잡힐 수 있다.
(아래의 코드는 나이순으로 정렬시 ROWNUM 기준 5번째부터 10번째까지의 사람들의 정보를 확인하는 쿼리문이다.)
SELECT SA2.* FROM(
SELECT ROWNUM R1, SA1.* FROM(
SELECT * FROM SEE_INFO ORDER BY AGE)SA1)SA2
WHERE R1 >= 5 AND R1 <= 10;
SA1 : 나이순으로 정렬한 SEE_INFO 테이블 데이터
R1: SA1에 대한 ROWNUM을 부여한 데이터
SA2: SA1에 R1(ROWNUM)을 부여한 데이터
위는 쿼리문에서 사용된 별칭들의 의미이다. 쿼리 진행 순서로는 먼저 SA1에서 전체 SEE_INFO 테이블의 나이 정보를 정렬해서 추출한다. 이후 해당 테이블의 ROWNUM(R1)을 매긴 정보를 SELECT 한다. 해당 SELECT 한 테이블 정보를 SA2 별칭에 담고 이후 WHERE 절에서 R1(ROWNUM)의 범위가 5에서 10인 테이블들만 걸러낸다. 마지막으로 SA2.*을 통해 해당 데이터 전체를 출력하면, 결과는 아래와 같다.
메인 이미지 출처: Photo by Justin W on Unsplash