오라클에서 rownum 은 쿼리가 실행될 때 결과 레코드에 번호를 나타내어 주는 필드이다.
물론 table을 만들 때 rownum을 만들어줄 필요는 없다.

어떠한 테이블이라도
"select rownum from boardtable" 의 형태로 쿼리를 날리면 레코드에 번호가 나타내어 주는 것을 볼 수 있을 것이다...

따라서 페이징을 위한 쿼리에서 우리는 rownum이 10 보다 크고 20보다 작은...
이런 식의 조건을 주어.. 원하는 범위의 레코드만 쿼리 할 수 있다..

select * from boardtable where rownum > 10 and rownum <= 20

그래서 위와 같이 쿼라하면 어떨까?
결과가 하나도 않나올 것이다.. 왜냐하면.. 쿼리가 실행되면 where 절 부분이 먼저 실행 될 것이고.. select 를 하기전에는 rownum이 없기 때문이다.
따라서, rownum을 긁어오는 쿼리를 한번 미리 해줄 필요가 잇다..

select * from (select rownum numrow , boardtable.* from boardtable) where numrow > 10 and numrow <= 20

order by 절을 사용하지 않는다면 이것만으로 우리는 행복할 수 있다.

select * from (select rownum numrow , boardtable.* from boardtable order by reg_date desc) where numrow > 10 and numrow <= 20

결과는 원하는 대로 되지 않음을 볼 수 있다.
이유는 아마도.... order by 가 rownum 값을 만드는데 영향을 못주는 것이라고 생각되는데.. 즉.. order by를 지정한다고 해도.. rownum은 최초의 order by 가 없는 상태로 만들어진다고 추측할 수 있다..
select rownum numrow , boardtable.* from boardtable order by reg_date desc
select rownum numrow , boardtable.* from boardtable
위의 두 쿼리는 실제로 rownum 값을 똑같이 만들어준다.. 물론 뿌리는 순서는 다르지만..

따라서 원하는대로 정렬을 할려면..

select rownum numrow , aa.* from ( select * from boardtable order by reg_date desc ) aa

위의 형태로 쿼리를 바꾸어 줘야 한다.
그런데 또 우리는 범위를 지정해야 하니까..

select rownum numrow , aa.* from ( select * from boardtable order by reg_date desc ) aa where numrow > 10 and numrow <= 20

하면 아무것도 안나오는 이유는 이미 설명했고..

select rownum numrow , aa.* from ( select * from boardtable order by reg_date desc ) aa where numrow > 10 and numrow <= 20

따라서...

select * from ( select rownum numrow , aa.* from ( select * from boardtable order by reg_date desc ) aa ) where numrow > 10 and numrow <= 20

위와 같이 해주면 되겟다..
그런데 좀 복잡하다.. 더구나 검색을 한번... 두번... 세번 을 하니...
데이타 양이 많다면 쿼리실행속도가 느려질 가능성이 있다..
물론 속도에 가장 큰 영향을 주는 것은 order by 이지만 ...
그래서 index를 만들고 hint 절을 써야할 이유가 생기는 것이다..
인덱스는 order by 를 하는 필드에 주면 된다..
따라서.. reg_date 필드에 인덱스를 주면 되고...
그러나 hint 절을 사용하려면 유니크 속성이 있어야 한다..
따라서.. 인덱스를 줄 때 reg_date 필드와 프라이머리 키 필드를 같이 걸어주면 유닉속성을 이용할 수 있다..

create unique index idx_board_reg_date on boardtable (reg_date, idx)

인덱스가 생성된다..

select /*+ index_desc(boardtable idx_board_reg_date) */ rownum, tvulist.* from tvulist

order by 없이 rownum이 제대로 긁어지나?

select * from (select /*+ index_desc(tvulist idx_board_reg_date) */ rownum as numrow, boardtable.* from boardtable ) where numrow > 10 and numrow <= 20

이제 위와 같이하면...
원하는 범위의 데이타를 가져올 수 있겠다..

만일 인덱스를 사용하지 않앗는데... 데이타가 튀어나오는 시간이 좀 늦는다 싶으면..
인덱스를 사용하라.. 행복할 것이다..

'먹고살기 > Oracle' 카테고리의 다른 글

Oracle Sql Case 사용법  (0) 2011.08.10
[오라클] SQL - UNION에 관한 SQL 규칙  (0) 2011.07.19
EXP-00091  (0) 2011.07.08
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기  (1) 2011.06.30
Sysdate  (0) 2011.06.02
EXP-00091 먹고살기/Oracle 2011. 7. 8. 08:12

EXP-00091: Exporting questionable statistics.
Export terminated successfully with warnings.
questionable statistics 란?
1. exp 받는 동안 row error가 있는 경우
2. client char set이나 nchar char set이 server char set이나 nchar char set
과 맞지 않는 경우
3. exp시 query 옵션이 사용된 경우
4. partitions, subpartions만 exp 받는 경우

위의 4가지 경우인 경우 위의 warning 이 나타납니다.
위의 4가지인 경우 기존의 통계정보와 달라질 수 있기 때문에 recalculate가 필요합니다.
oracle 9버전부터 export시 default로 기존의 통계정보를 export받는데
export 받기 전 정상적으로 analyze가 되지 않았다면 위에 해당하는 에러가 발생하게 됩니다.

answer1>
통계정보를 무시하고 export 할려고 한다면..옵션절에 statistics = none 로 써
주시고 export받으면 됩니다.
answer2>
imp받으실때 statistics=safe로 받으면 됩니다.
여러 exp 파일이 있는 경우 저 warning이 났는지 안났는지 모르기때문에 safe 옵션을 쓰면 재계산이 필요한 경우는 해주고 안필요하면 안하고 넘어가게 됩니다.

[출처] EXP-00091|작성자 소나무

'먹고살기 > Oracle' 카테고리의 다른 글

[오라클] SQL - UNION에 관한 SQL 규칙  (0) 2011.07.19
ORACLE ROWNUM 활용  (0) 2011.07.08
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기  (1) 2011.06.30
Sysdate  (0) 2011.06.02
SQL _ HAVING  (0) 2011.04.29

select distinct field1

from tb_test

이렇게 하면 field1에 있는 데이터 중 중복을 제거하고 유니크 한 값들만 나온다.

그러나 시간 개념이 들어가서 최신의 데이터에 해당하는 row의 값을 다 가져 오고 싶다면?

distinct에 시간까지 걸면 모든 데이터가 다 유니크 해버린다.

oracle db 데이터 중 특정 필드의 중복을 제거하고 최신의 데이터 1개만 가져오기.

숨어 있던 rowid가 이때 도움을 준다.

select *

from tb_test

where reg_tm between start_tm and end_tm

and rowid in (select max(rowid) from tb_test group by field1)

중복이 되면 안되는 필드를 group by 해서 rowid를 큰 것 순으로 뽑아내면 된다.

...라고 썼는데, 생각해보니.. scan 범위를 더 줄일 수 있을 것 같다.

물론 이건 환경과 쓰는 사람 마음에 따라 다르다. 내가 찾은 예제에선 저렇게 되어 있었고..

나는 시간 범위 내에서 중복된 값 중 최신의 것만 찾아내면 되니까.

select *

from tb_test

where rowid in (select max(rowid) from tb_test where reg_tm between start_tm and end_tm group by field1)

요렇게 작성하면 스캔 범위가 줄어들어 위의 쿼리보단 성능향상에 도움이 될 수 있을 것 같다.

ps. 스크랩 하시는 분들이 많아져서 추가 사실을 덧붙입니다.

이 구문은 rowid가 숫자일 경우에만 유효합니다


'먹고살기 > Oracle' 카테고리의 다른 글

ORACLE ROWNUM 활용  (0) 2011.07.08
EXP-00091  (0) 2011.07.08
Sysdate  (0) 2011.06.02
SQL _ HAVING  (0) 2011.04.29
SQL _ 상관서브쿼리  (0) 2011.04.29
쉘 스크립트 먹고살기/Unix 2011. 6. 30. 16:20

'먹고살기 > Unix' 카테고리의 다른 글

공백제거  (5) 2014.03.21
리눅스 실무 명령어  (0) 2011.04.29
리눅스 명령어  (0) 2011.04.29
Sysdate 먹고살기/Oracle 2011. 6. 2. 09:17

1. 10분에 한번씩 실행하는 경우
sysdate + 1/24/6 또는 sysdate + 1/144
-> 1/24 (1시간-60분) / 6 : 10분 단위
1/144 : 24*6 으로 나누어도 같은 의미가 된다.
2. 1분에 한번으로 지정하는 경우
sysdate + 1/24/60 또는 sysdate + 1/1440
3. 매일 새벽 2시로 지정하는 경우
trunc(sysdate) + 1 + 2/24 -> 다음날 새벽 2시를 지정함.
4. 매일 밤 11시로 지정하는 경우
trunc(sysdate) + 23/24 -> 오늘 밤 11시를 지정했음.
현재 job 이 있는지 없는지는 user_jobs 뷰를 보시면 됩니다.

5분전 Sysdate - 1/24/12
10분전 Sysdate - 1/24/6 

'먹고살기 > Oracle' 카테고리의 다른 글

EXP-00091  (0) 2011.07.08
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기  (1) 2011.06.30
SQL _ HAVING  (0) 2011.04.29
SQL _ 상관서브쿼리  (0) 2011.04.29
SQL _ HAVING_2  (0) 2011.04.29