Programing

Oracle ORDER BY 및 ROWNUM을 올바르게 사용하는 방법은 무엇입니까?

crosscheck 2020. 8. 6. 07:56
반응형

Oracle ORDER BY 및 ROWNUM을 올바르게 사용하는 방법은 무엇입니까?


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

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

SQL 서버 :

SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC

=> 가장 최근의 레코드를 반환합니다

그러나 오라클 :

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 로 주문하십시오 "라고 말합니다. 그리고 그것은 당신이 의도 한 것이 아닙니다.

하위 쿼리 방법은 Oracle에서이를 수행하기위한 적절한 방법입니다.

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

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

이 사용 사례에서 제안하는 대안은 MAX (t_stamp)를 사용하여 최신 행을 얻는 것입니다.

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

My coding pattern preference (perhaps) - reliable, generally performs at or better than trying to select the 1st row from a sorted list - also the intent is more explicitly readable.
Hope this helps ...

SQLer


Documented couple of design issues with this in a comment above. Short story, in Oracle, you need to limit the results manually when you have large tables and/or tables with same column names (and you don't want to explicit type them all out and rename them all). Easy solution is to figure out your breakpoint and limit that in your query. Or you could also do this in the inner query if you don't have the conflicting column names constraint. E.g.

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')  

will cut down the results substantially. Then you can ORDER BY or even do the outer query to limit rows.

Also, I think TOAD has a feature to limit rows; but, not sure that does limiting within the actual query on Oracle. Not sure.

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

반응형