복붙노트

[SQL] 오라클 TOP N 행을 정렬

SQL

오라클 TOP N 행을 정렬

나는 Oracle 테이블이 날짜별로 정렬에서 상위 N 행을 좀하고 싶습니다.

일반적인 방법은이 작업을 수행하기 위해, 나는 SO에서 찾을 수있는 모든 질문에 대한이 솔루션 반환 / 구글.

Select *
from
(select * from
myTable 
ordered by Date desc)
where rownum < N

myTable에가있는 것 행의 엄청난 금액을 포함하고 있기 때문에이 솔루션은 내 경우 비현실적이다 오라클은 하위 쿼리의 모든 행을 반환하는 데 시간이 너무 오래 복용으로 이어질.

질문은 하위 쿼리에서 반환 ORDERED 행의 수를 제한하는 방법은 무엇입니까?

해결법

  1. ==============================

    1.오라클은 최초의 N을 필터링하기 전에 하위 쿼리의 모든 행을 반환해야 당신의 추론은 잘못된 것입니다. 그것은 하위 쿼리에서 행을 가져 오는 시작하고 N 행을 반환했을 때 중지됩니다.

    오라클은 최초의 N을 필터링하기 전에 하위 쿼리의 모든 행을 반환해야 당신의 추론은 잘못된 것입니다. 그것은 하위 쿼리에서 행을 가져 오는 시작하고 N 행을 반환했을 때 중지됩니다.

    그런 말을하는 데, 그것은 오라클은 테이블에서 모든 행을 선택하고이를 반환 시작하기 전에 그들을 정렬 할 필요가 있다고 할 수있다. 컬럼에 인덱스가 ORDER BY 절에서 사용되는이 있다면, 그것은하지 않을 수 있습니다.

    오라클은 다른 DBMS와 같은 위치에있다 : 당신은 당신에 의해 주문하는 칼럼에 아무런 인덱스와 큰 테이블이있는 경우 어떻게 아마도 첫번째 점점 모든 행없이 상위 N있는 행을 알고 그들을 정렬 할 수 있습니까?

  2. ==============================

    2.다음은 내가 일반적으로 (이 경우 매김 쿼리) 상위 N 형 쿼리를 사용하는 것입니다 :

    다음은 내가 일반적으로 (이 경우 매김 쿼리) 상위 N 형 쿼리를 사용하는 것입니다 :

    select * from (
      select a.*, rownum r
      from (
        select *
        from your_table
        where ...
        order by ...
      ) a
      where rownum <= :upperBound
    )
    where r >= :lowerBound;
    

    나는 보통 내부 쿼리의 종류에 인덱스 컬럼을 사용하고 ROWNUM의 사용은 오라클이 수 (stopkey) 최적화를 사용할 수 있다는 것을 의미합니다. 따라서, 반드시 전체 테이블 스캔을하지 않을 :

    create table t3 as select * from all_objects;
    alter table t3 add constraint t_pk primary key(object_id);
    analyze table t3 compute statistics;
    
    delete from plan_table;
    commit;
    explain plan for
    select * from (
      select a.*, rownum r
      from (
        select object_id, object_name
        from t3
        order by object_id
      ) a
      where rownum <= 2000
    )
    where r >= 1;
    
    select operation, options, object_name, id, parent_id, position, cost, cardinality, other_tag, optimizer
    from plan_table
    order by id;
    

    당신은 오라클이 t_pk를 사용하여 스캔 전체 인덱스를 수행 확인할 수 있습니다. 또한 stopkey 옵션의 사용을 확인합니다.

    내 대답을 설명 희망)

  3. ==============================

    3.당신은 많은 데이터가있는 경우로 주문 무거운 작동 될 수 있습니다. 당신의 실행 계획을 살펴보십시오. 데이터가 실시간이 아닌 경우에 당신은 선택의이 종류에 중대한보기를 만들 수 있습니다 ...

    당신은 많은 데이터가있는 경우로 주문 무거운 작동 될 수 있습니다. 당신의 실행 계획을 살펴보십시오. 데이터가 실시간이 아닌 경우에 당신은 선택의이 종류에 중대한보기를 만들 수 있습니다 ...

  4. ==============================

    4.ORACLE (8.0) 이전 버전에서는 하위 쿼리에서 ORDER BY 절을 사용할 수있는 가능성이 없습니다. UNION 연산자의 마법 : 그래서, 단지 아직 고대 버전을 사용하는 사람들을 위해, 처리하는 또 다른 방법이있다. UNION 쿼리의 열으로 레코드를 정렬합니다 :

    ORACLE (8.0) 이전 버전에서는 하위 쿼리에서 ORDER BY 절을 사용할 수있는 가능성이 없습니다. UNION 연산자의 마법 : 그래서, 단지 아직 고대 버전을 사용하는 사람들을 위해, 처리하는 또 다른 방법이있다. UNION 쿼리의 열으로 레코드를 정렬합니다 :

    예:

    SELECT * FROM
    (SELECT EMP_NO, EMP_NAME FROM EMP_TABLE
    UNION
    SELECT 99999999999,'' FROM DUAL)
    WHERE ROWNUM<=5
    where 99999999999 is bigger then all values in EMP_NO;
    

    또는, 당신이 가장 높은 5 급여와 TOP 5 급여 직원을 선택하려면 :

    SELECT EMP_NO, EMP_NAME, 99999999999999-TMP_EMP_SAL
    FROM
    (SELECT 99999999999999-EMP_SAL TMP_EMP_SAL, EMP_NO, EMP_NAME 
    FROM EMP_TABLE
    UNION
    SELECT 99999999999999,0,'' FROM DUAL)
    WHERE ROWNUM<=5;
    

    문안 인사,

    버질 Ionescu

  5. from https://stackoverflow.com/questions/6858325/oracle-top-n-ordered-rows by cc-by-sa and MIT license