2012-05-23 9 views
0

오라클 9.2.0.8에서는 특정 필드 (LAB_SEQ)가 최대 인 레코드 집합을 반환해야합니다 (순차적 VARCHAR 배열 '0001', '0002'등) 다른 필드 (WO_NUM)마다. 최대 값을 선택하려면 내림차순으로 정렬하고 첫 번째 행을 선택하려고합니다. StackOverflow에서 찾을 수있는 유일한 방법은 상관 관계가있는 하위 쿼리를 사용하는 것입니다.Oracle에서 상관 관계 서브 쿼리 피하기

SELECT lt.WO_NUM, lt.EMP_NUM, lt.LAB_END_DATE, lt.LAB_END_TIME 
FROM LAB_TIM lt WHERE lt.LAB_SEQ = (
    SELECT LAB_SEQ FROM (
     SELECT lab.LAB_SEQ FROM LAB_TIM lab WHERE lab.CCN='1' AND MAS_LOC='1' 
      AND lt.WO_NUM = lab.WO_NUM ORDER BY ROWNUM DESC 
    ) WHERE ROWNUM=1 
) 

그러나,이 lt.WO_NUM 오류에 대해 잘못된 식별자를 반환한다 : 그럼 나는 각 WO_NUM에 대해 원하는 행을 얻을 수있는 외부 쿼리의 WHERE 절에서이 최대 값을 사용합니다. 연구에 따르면 ORACLE 8은 상관 관계가있는 하위 쿼리 만 한 단계 깊게 허용하며 하위 쿼리를 피하기 위해 재 작성을 제안합니다. 최대 값 선택에 대한 논의는 할 수 없습니다. 이 성명을 실행하는 데 도움이 될 경우 대단히 감사하겠습니다.

+3

ROWNUM의 주문은 여기에별로 도움이되지 않습니다. – DCookie

답변

3

귀하의 상관 하위 쿼리는 오라클 9.2에 있기 때문에, 아마 상관 하위 쿼리를 사용하는 것이 더 효율적입니다 뭔가

SELECT lt.WO_NUM, lt.EMP_NUM, lt.LAB_END_DATE, lt.LAB_END_TIME 
FROM LAB_TIM lt WHERE lt.LAB_SEQ = (
    SELECT max(lab.LAB_SEQ) 
    FROM LAB_TIM lab 
    WHERE lab.CCN='1' AND MAS_LOC='1' 
     AND lt.WO_NUM = lab.WO_NUM 
) 

처럼 될 필요가있다. 술어 lab.CCN='1' AND MAS_LOC='1'이 현재 쿼리에서 무엇을하는지 확신 할 수 없으므로 분석 함수 접근 방식으로 변환하는 방법을 잘 모르겠습니다. LAB_SEQWO_NUM의 조합이 LAB_TIM에서 고유하지 않습니까? 모든 WO_NUM에 대해 단일 고유 행을 얻으려면 CCNMAS_LOC에 술어를 추가해야합니까? 아니면 출력에서 ​​행 수를 줄이기 위해이 술어를 사용하고 있습니까? 기본적인 접근 방법은 무엇인가와 같은

SELECT * 
    FROM (SELECT lt.WO_NUM, 
       lt.EMP_NUM, 
       lt.LAB_END_DATE, 
       lt.LAB_END_TIME, 
       rank() over (partition by wo_num 
           order by lab_seq desc) rnk 
      FROM LAB_TIM lt) 
    WHERE rnk = 1 

될 것입니다하지만 CCNMAS_LOC는 분석 함수 또는 그들이 WHERE 절에 추가 될 필요가 있는지 여부를 ORDER BY 절에 추가 할 필요가 있는지 나에게 분명하지 않다.

+1

+1, 8i에는 이미 [analytics] (http://docs.oracle.com/cd/A87860_01/doc/server.817/a85397/function.htm#81409)가 있습니다. –

+0

@VincentMalgrat - 네 말이 맞아. - 8.1.6에서 소개 된 것처럼 보입니다. –

+0

고마워, 저스틴. 이것이 나의 목표를 달성하는 동안, 그것은 비극적 인 비효율을 겪는다. max() 함수는 테이블의 모든 항목 (큰 수)을 반복하므로, 행이 실제로 순서대로 있다는 사실을 이용하고 싶습니다. 나는 ROWNUM에 의한 분류가 LAB_SEQ보다 더 효율적이라고 생각한다. 왜냐하면 문자열을 비교하는 것은 시간 소모적이기 때문이다. 제안하신 검색어가 약 5 분 동안 실행되었으며 끝이 보이지 않습니다. – user1412922

0

특히 테이블에 인덱스가있는 경우 상관 관계가있는 하위 쿼리가 더 좋은 경우입니다. 그러나 상관 관계가있는 하위 쿼리를 조인으로 다시 쓸 수 있어야합니다.

나는 상관 하위 쿼리하지 않고, 다음과 같은 동등한 생각 :

SELECT lt.WO_NUM, lt.EMP_NUM, lt.LAB_END_DATE, lt.LAB_END_TIME 
FROM (select *, rownum as r 
     from LAB_TIM lt 
    ) lt join 
    (select wo_num, max(r) as maxrownum 
     from (select LAB_SEQ, wo_num, rownum as r 
      from LAB_TIM lt 
      where lab.CCN = '1' AND MAS_LOC = '1' 
      ) 
    ) ltsum 
    on lt.wo_num = ltsum.wo_num and 
     lt.r = ltsum.maxrownum 

내가 오라클 BY ORDER 같은 일에 rownums 작동 방법에 대한 좀 확실 해요.