database/Oracle

[Oracle] rownum

솧이 2022. 9. 2. 22:40

Q. select 결과물 중 맨 위의 5개만 출력해보고 싶으면 어떻게 해야 할까?

     select 결과물 중 n번째부터 m개를 출력하고 싶다면?

     ex) 게시판, 페이징,,

 

DBMS 마다 구현 방법 다름
MYSQL : LIMIT -> 제일 깔끔하게 나온다
MS SQL server : TOP
ORACLE : ROWNUM -> 제일 더럽게 나온다

 

 

rownum : select 시 oracle에서 붙여주는 행 번호 

SELECT ROWNUM, empno, ename, sal FROM t_emp;

 

상위 5개만 출력하기

SELECT empno, ename, sal From t_emp
WHERE rownum <= 5
ORDER BY empno DESC;

 

 

* rownum은 select 이후에 시행된다

고로 select 이후에 order by를 하면 순서가 망가질 수 있다

이 테이블에서 기본키는 empno!

SELECT rownum, empno, ename, sal FROM t_emp 
WHERE rownum <= 5
ORDER BY sal desc; -- 순서 엉망 pk 아닌걸로 ORDER BY 했을 때!

 

 

Q. order by 없을 때 무슨 순서대로 값이 정렬될까?
pk의 오름차순. pk가 인덱스로 설정되는데 그 pk의 오름차순 순서대로 나온다.

 

 

 

Q. rownum 범위가 1을 포함하지 않으면 안되나?

값이 나오지 않는다

rownum은 select 수행한 붙여진다

rownum <= 5 은 1-5 나온다는 보장이 있는데 rownum > 5는 몇번까지 나온다는 보장이 없으니 동작을 안하는 것 같다

그러면 상위 5개를 어떻게 뽑아낼 수 있을까?

SELECT rownum, empno, ename, sal 
FROM t_emp 
WHERE rownum > 5 -- 안된다 why?? 휴.. 응? 15:23
ORDER BY empno desc;

 

A. 6행부터 10행까지 출력 (2페이지) mysql은 나오나 oracle은 나온다 -> 해결방법 서브쿼리 사용!

첫번째 ) select문 생성

SELECT empno, ename, sal FROM t_emp ORDER BY empno DESC

 

두번째 ) from절에 넣기

* rownum에 별명을 붙여줘야 한다

SELECT rownum AS rnum, T.*
FROM (SELECT empno, ename, sal FROM t_emp ORDER BY empno DESC) T;

 

세번째 ) 위의 결과를 sub query에 넣을 것

* 이제부터 rownum은 일반적인 column이다. sub query의 결과물이다! 이상하게 꼬였던 rownum이 아니다!

SELECT * FROM
(
    SELECT rownum AS rnum, t.* -- rnum 별명 붙여야 한다
    FROM (SELECT empno, ename, sal FROM t_emp ORDER BY empno DESC) t;
)
;

 

네번째 ) 정렬해보자

* 완성! inline view와 rownum 활용!

SELECT * FROM
(
	SELECT ROWNUM AS RNUM, T.*
	FROM (SELECT empno, ename, sal FROM t_emp ORDER BY empno DESC) T
)
--WHERE RNUM >= 6 AND RNUM < 6 + 5  -- 2페이지
WHERE RNUM >= 11 AND RNUM < 11 + 5  -- 3페이지
;

총 14개의 row이므로 3페이지가 나온다

 

 

 

row_number() over (order by 정렬 컬럼1, ... )

특정 column의 값을 기준으로 정렬한 뒤 순서를 매기기

사용법 : SELECT ROW_NUMBER() OVER (ORDER BY 정렬 컬럼, ... ), 서브쿼리컬럼 FROM  서브쿼리

 

* over 키워드가 같이 나와야 한다

  sal 역순으로 한 값이 나온다

* sal 역순으로 한 다음에 rnum이 나온다. 이게 rownumber가 해주는 역할이다.

SELECT ROW_NUMBER() OVER (ORDER BY sal DESC) AS RNUM, T.*
FROM (SELECT empno, ename, sal FROM t_emp ORDER BY empno DESC) T

 

 

row_number() 는 '출력 순서'

rank() 는 '순위 통계' - 동일한 값은 동일한 rank로 1,2,2,4,5

SELECT ROW_NUMBER OVER(ORDER BY total DESC) "RNUM",
       RANK() OVER(ORDER BY total DESC) "RANK",
       T.*
FROM (SELECT s.name, e.total FROM t_student s, t_exam01 e
	  WHERE s.studno = e.studno
 ) T;

 

 

'database > Oracle' 카테고리의 다른 글

[Oracle] View  (0) 2022.09.04
[Oracle] 집합연산자 set operator  (0) 2022.09.02
[Oracle] DML sub query  (0) 2022.09.02
[Oracle] 위치별 sub query  (0) 2022.09.02
[Oracle] 상호연관 sub query  (0) 2022.09.02