codememo

Oracle ORDER BY 및 ROWNUM을 올바르게 사용하는 방법

tipmemo 2023. 2. 18. 20:07
반응형

Oracle ORDER BY 및 ROWNUM을 올바르게 사용하는 방법

당사 제품과 호환되도록 저장 프로시저를 SQL Server에서 Oracle로 변환하는 데 어려움을 겪고 있습니다.

타임스탬프에 따라 일부 테이블의 최신 레코드를 반환하는 쿼리가 있습니다.

SQL Server:

SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC

=> 그러면 최신 레코드가 반환됩니다.

그러나 Oracle:

SELECT *
FROM raceway_input_labo 
WHERE  rownum <= 1
ORDER BY t_stamp DESC

=> 그러면 가장 오래된 레코드(인덱스에 따라 다름)가 반환됩니다.ORDER BY스테이트먼트!

요건을 충족하기 위해 Oracle 쿼리를 다음과 같이 캡슐화했습니다.

SELECT * 
FROM 
    (SELECT *
     FROM raceway_input_labo 
     ORDER BY t_stamp DESC)
WHERE  rownum <= 1

그리고 그것은 동작한다.하지만 제게는 끔찍한 해킹처럼 들리는데요, 특히 제가 관련 테이블에 많은 기록을 가지고 있다면요.

이것을 달성하는 가장 좋은 방법은 무엇입니까?

where스테이트먼트가 실행되기 전에order by원하는 질문은 "첫 번째 행을 선택한 후 다음 순서로 주문합니다. t_stamp desc"라고 써있네요.그건 당신이 의도한 바가 아니에요.

이 작업을 수행하려면 오라클에서 하위 쿼리 방법을 사용하는 것이 좋습니다.

두 서버에서 모두 사용할 수 있는 버전을 원하는 경우 다음을 사용할 수 있습니다.

select ril.*
from (select ril.*, row_number() over (order by t_stamp desc) as seqnum
      from raceway_input_labo ril
     ) ril
where seqnum = 1

바깥쪽*마지막 열에 "1"이 반환됩니다.이 문제를 방지하려면 열을 개별적으로 나열해야 합니다.

사용하다ROW_NUMBER()대신. ROWNUM가짜 초콜릿이고ROW_NUMBER()함수입니다.이들 간의 차이를 읽고 아래 쿼리의 출력 차이를 확인할 수 있습니다.

SELECT * FROM (SELECT rownum, deptno, ename
           FROM scott.emp
        ORDER BY deptno
       )
 WHERE rownum <= 3
 /

ROWNUM    DEPTNO    ENAME
---------------------------
 7        10    CLARK
 14       10    MILLER
 9        10    KING


 SELECT * FROM 
 (
  SELECT deptno, ename
       , ROW_NUMBER() OVER (ORDER BY deptno) rno
  FROM scott.emp
 ORDER BY deptno
 )
WHERE rno <= 3
/

DEPTNO    ENAME    RNO
-------------------------
10    CLARK        1
10    MILLER       2
10    KING         3

Oracle 12c 이후 행 제한 절을 사용하여 이 작업을 수행할 수 있게 되었습니다.

SELECT *
FROM raceway_input_labo 
ORDER BY t_stamp DESC
FETCH FIRST ROW ONLY

또는 다양한 시나리오(처음 n행, 동점 처리 등)에 대한 많은 대안.

상기의 코멘트로, 이것에 관한 몇개의 설계상의 문제를 문서화합니다.요약하자면, Oracle에서는 열 이름이 같은 큰 테이블 및/또는 테이블이 있는 경우(또한 모두 명시적으로 입력하고 이름을 변경하지 않으려면) 결과를 수동으로 제한해야 합니다.간단한 해결책은 중단점을 파악하여 쿼리에서 이를 제한하는 것입니다.또는 충돌하는 열 이름 제약 조건이 없는 경우 내부 조회에서도 이 작업을 수행할 수 있습니다.예.

WHERE m_api_log.created_date BETWEEN TO_DATE('10/23/2015 05:00', 'MM/DD/YYYY HH24:MI') 
                                 AND TO_DATE('10/30/2015 23:59', 'MM/DD/YYYY HH24:MI')  

결과를 대폭 삭감할 수 있습니다.그런 다음 ORDER BY를 사용하거나 외부 쿼리를 수행하여 행을 제한할 수 있습니다.

또한 TOAD에는 행을 제한하는 기능이 있다고 생각합니다만, Oracle의 실제 쿼리 내에서 제한되는지는 확실하지 않습니다.확실하진 않다.

이 사용 예에서는 MAX(t_stamp)를 사용하여 최신 행을 가져오는 것이 좋습니다.

select t.* from raceway_input_labo t
where t.t_stamp = (select max(t_stamp) from raceway_input_labo) 
limit 1

코딩 패턴 선호도(아마도) - 정렬된 목록에서 첫 번째 행을 선택하는 것보다 신뢰성이 높고 성능이 더 우수합니다. 또한 의도도 더 명확하게 읽을 수 있습니다.
...

SQLer

언급URL : https://stackoverflow.com/questions/15091849/how-to-use-oracle-order-by-and-rownum-correctly

반응형