저장 프로 시저를 SQL Server에서 Oracle로 변환하여 제품과 호환되도록하는 데 어려움을 겪고 있습니다.
타임 스탬프를 기반으로 일부 테이블의 최신 레코드를 반환하는 쿼리가 있습니다.
SQL 서버 :
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 로 정렬 “이라고 말합니다. 그리고 그것은 당신이 의도 한 것이 아닙니다.
하위 쿼리 방법은 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
내 코딩 패턴 선호도 (아마도)-신뢰할 수 있고, 일반적으로 정렬 된 목록에서 첫 번째 행을 선택하는 것보다 더 나은 성능을 발휘합니다. 또한 의도가 더 명시 적으로 가독성이 높습니다.
도움이 되었기를 바랍니다 …
SQLer
답변
위의 주석에서 이와 관련된 몇 가지 디자인 문제를 문서화했습니다. 짧은 이야기, 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의 실제 쿼리 내에서 제한되는지 확실하지 않습니다. 확실하지 않다.