Oracle SELECT TOP 10 레코드


144

Oracle의 SQL 문에 큰 문제가 있습니다. 다른 select 문에서 목록에없는 STORAGE_DB에서 주문한 TOP 10 레코드를 선택하고 싶습니다.

이것은 모든 레코드에 대해 잘 작동합니다.

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
      STORAGE_GB IS NOT NULL AND 
        APP_ID NOT IN (SELECT APP_ID
                       FROM HISTORY
                        WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

하지만 내가 추가 할 때

AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC

어떤 종류의 "무작위"기록을 받고 있습니다. 주문 전에 제한이 있기 때문에 생각합니다.

누군가 좋은 해결책이 있습니까? 다른 문제 :이 쿼리는 실제로 느립니다 (10k + 레코드)



답변:


199

아래와 같이 현재 쿼리를 하위 쿼리에 넣어야합니다.

SELECT * FROM (
  SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC )
WHERE ROWNUM <= 10

Oracle 은 반환 된 결과에 rownum 을 적용 합니다.
결과가 반환 된 후 결과를 필터링해야하므로 하위 쿼리가 필요합니다. RANK () 함수를 사용하여 Top-N 결과를 얻을 수도 있습니다 .

성능을 위해 NOT EXISTS대신 사용하십시오 NOT IN. 자세한 내용은 이것을 참조하십시오 .


이 시나리오에서는 NOT EXISTS가 작동하지 않습니다 (유효하지 않은 관계 연산자) APP_ID NOT EXISTS (SELEC ...)
opHASnoNAME

3
어떤 사람들은 이것이 사람들을 오라클로 끌기 쉽다고 말할 수 있습니다.
MrBoJangles

2
FETCH NEXT N ROWS ONLY아래 답변을 확인하십시오 .
Mohnish

@Padmarag : 행 번호가 이와 같은 쿼리에 적용되는 경우-someColumn = '123'이고 행 번호 <= 3 인 SomeTable에서 *를 선택하십시오. 의 결과를 선택한 후에는 [SomeTable에서 선택 * 어디 someColumn = '123']
Shirgill 인 Farhan

55

Oracle 12c를 사용하는 경우 다음을 사용하십시오.

FETCH NEXT N ROWS 만 해당

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC
FETCH NEXT 10 ROWS ONLY

추가 정보 : http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html


2
이것은 다른 대답에 비해 금이다
aswzen

동의 aswzen
Austin Springer

1
이 답변에 100 upvotes를주고 싶습니다! 그러나 슬프게도, 나는 오직 하나만 수여합니다. 하나입니다!
eidylon

23

성능 저하와 관련하여 여러 가지가있을 수 있으며 실제로 별도의 질문이어야합니다. 그러나 문제가 될 수있는 분명한 것이 있습니다.

WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

HISTORY_DATE가 실제로 날짜 열이고 인덱스가 있으면이 다시 쓰기가 더 잘 수행됩니다.

WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')  

데이터 유형 변환이 B- 트리 인덱스 사용을 비활성화하기 때문입니다.



11

ORDER BY 이전에 ROWNUM이 적용 되었기 때문에 분명히 임의의 세트를 얻습니다. 따라서 쿼리는 처음 10 개의 행을 가져 와서 정렬합니다 .0 상위 10 개의 급여를 선택하려면 하위 쿼리에서 분석 함수를 사용하고 다음을 필터링해야합니다.

 select * from 
     (select empno,
             ename,
             sal,
             row_number() over(order by sal desc nulls last) rnm
    from emp) 
 where rnm<=10
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.