2012-11-14 1 views
0

Oracle 데이터베이스에 대한 쿼리를 실행 중입니다.외부 조인에서 중복 행 제거

목표는 다음과 같은 열이 반환입니다 -

  1. 문서 ID를
  2. 문서 생성 날짜
  3. 기구 코드
  4. 문서 상태
  5. 총액

문제 I 실행하고있는 것은 Organization Co 드. 여러 조직 코드가있는 문서 ID를 가질 수 있습니다. 난 단지 1 개 인스턴스를 원하는 - (있는 경우) 나는

여기

내가 현재 가지고있는 것입니다 나머지에 대해 걱정하지 않는다 -

SELECT * FROM (SELECT DISTINCT (K_HDR.DOC_HDR_ID), 
     K_HDR.CRTE_DT, 
     FS_EXT.VAL AS ORG_CODE, 
     REQ.REQS_STAT_CD, 
     FS_DOC.FDOC_TOTAL_AMT 
    FROM PUR_REQS_T REQ, 
     KREW_DOC_HDR_T K_HDR, 
     FS_DOC_HEADER_T FS_DOC, 
     KREW_DOC_HDR_EXT_T FS_EXT 
    WHERE REQ.FDOC_NBR = K_HDR.DOC_HDR_ID AND 
     FS_DOC.FDOC_NBR = REQ.FDOC_NBR AND 
     REQ.FDOC_NBR = FS_EXT.DOC_HDR_ID(+) AND 
     FS_EXT.KEY_CD(+)= 'organizationCode' AND 
     (K_HDR.CRTE_DT BETWEEN TO_DATE('2011-10-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') 
     AND 
     TO_DATE('2012-09-30 23:59:59', 'YYYY-MM-DD HH24:MI:SS'))) 
    FINAL_SEARCH ORDER BY FINAL_SEARCH.CRTE_DT; 

다음 쿼리는 14,933 행을 반환합니다. 올바른 행의 크기는 14,789입니다.

범인은 조직 코드입니다. 나는 내가 보는 결과 세트를 찾고 있어요으로 예를 들어 다음 -

DOC_ID CRTE_DT  ORG_CD STAT TOTAL 
. 
. 
. 
496256 5-OCT-11  0  CLOS 2779.89 
496258 5-OCT-11  8050  CLOS 1737.5 
496258 5-OCT-11  8000  CLOS 1737.5 
. 
. 
. 

은 어떻게 FS_EXT 표에 살고있는 496,258의 짜증나는 2 예를 제거합니까? 당신 만 MIN 조직 코드를 얻을 수있는 GROUP BY을 사용하는 SELECT 하나의 전체를 포장 할 수

+0

보관할 레코드의 버전은 무엇입니까? 위의 예에서 레코드를 ORG_CD = 8050 또는 8000으로 유지하려고합니다. 또는 더 일반적으로 - 중복이있을 때 선택 기준을 정의하는 것은 무엇입니까? –

+0

@Rishabh Sagar - 내가 만나는 첫 번째 인스턴스를 가져와 뒤 따르는 인스턴스를 무시해야합니다. –

+0

'처음'은 어떤 기준을 기반으로합니까? 데이터에는 고유 한 순서가 없습니다. 'fs_ext'에 관련성이있는 또 다른 필드가 있습니까? 또한 특히 외부 조인을 사용할 때이 오래된 스타일 대신'join' 구문을 사용하는 것이 좋습니다. –

답변

1

(물론 나는 중복 값의 동일한 유형의 다른 인스턴스를 제거합니다).

+0

흥미로운 제안입니다. 그건 그냥 작동 할 수도 있습니다. –

+0

나는 그것이 일할 것이라고 확신한다 :) 그것은 가장 우아한 접근이 아닐 수도 있지만, 그것은 당신이 필요로하는 것을 절대적으로 할 것이다. – StilesCrisis

+0

@StileCrisis - 항상 조직 코드가 아닌 조직 코드의 첫 번째 인스턴스를 가져와야합니다. 나는 그 방망이를 바로 잡았어야했다. 그 요구 사항이 없다면 좋은 제안. –

1

이렇게 - FS_EXT 테이블의 다른 열을 사용하여 Org 코드의 첫 번째 인스턴스까지 추가로 필터링했습니다. 여기

내가 문서 ID 만 표시 항목을 필터링 열에서 찾고 경우처럼 FS_EXT 테이블 모습입니다 = 496258.
(마음을 행의 수가 다른 어떤 지정된 문서가 id가있을 수 있음)

DOC_HDR_EXT_ID  DOC_HDR_ID  KEY_CD      VAL 
13318096   496258   documentDescription   misc items 
13318098   496258   organizationDocNumber  (null) 
13318099   496258   statusDescription   Closed 
13318101   496258   chartAndOrgCodeForResult KS-1234 
13318102   496258   vendorName     APPLE COMPUTERS 
13318103 
. 
. 
. 
. 
. 
13318115   496258   organizationCode   8000 
13318116 
. 
. 
. 
1338118   496258   organizationCode   8050 

그리고 JOIN 연산을 우회하는 새로운 쿼리가 있습니다.

대신 SUBQUERY를 사용합니다. OrganizationCode의 첫 번째 인스턴스를 가져 오려면 DOC_HDR_EXT_ID 열에서 MIN 연산자를 사용하고 해당 ID를 사용하여 organizationCode VAL을 검색 한 다음이를 기본 QUERY로 다시 전달합니다.

SELECT * FROM (SELECT DISTINCT (K_HDR.DOC_HDR_ID), 
     K_HDR.CRTE_DT, 
     (SELECT KS_EXT.VAL AS ORG_CODE 
       FROM KREW_DOC_HDR_EXT_T KS_EXT 
       WHERE KS_EXT.DOC_HDR_EXT_ID =(
       SELECT MIN(DOC_HDR_EXT_ID) 
       FROM KREW_DOC_HDR_EXT_T FS_EXT_INNER 
       WHERE FS_EXT_INNER.DOC_HDR_ID = K_HDR.DOC_HDR_ID 
       AND FS_EXT_INNER.KEY_CD = 'organizationCode')) AS ORG_CODE, 
     REQ.REQS_STAT_CD, 
     FS_DOC.FDOC_TOTAL_AMT 
     FROM PUR_REQS_T REQ, 
     KREW_DOC_HDR_T K_HDR, 
     FS_DOC_HEADER_T FS_DOC, 
     KREW_DOC_HDR_EXT_T FS_EXT 
     WHERE REQ.FDOC_NBR = K_HDR.DOC_HDR_ID AND 
       FS_DOC.FDOC_NBR = REQ.FDOC_NBR AND 
       REQ.FDOC_NBR = FS_EXT.DOC_HDR_ID(+) AND 
       FS_EXT.KEY_CD(+)= 'organizationCode' AND 
       (K_HDR.CRTE_DT BETWEEN TO_DATE('2011-10-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2012-09-30 23:59:59', 'YYYY-MM-DD HH24:MI:SS'))) 
    FINAL_SEARCH ORDER BY FINAL_SEARCH.CRTE_DT; 

@Alex Poole 및 @StilesCrisis. 이 문제에 대한 내 접근 방법에 대해 다르게 생각하게 만들고 내 솔루션은 두 가지 제안을 모두 통합합니다. Stiles의 MIN 접근 방식과 Alex Poole 당 다른 열 필터링.

+1

너무 자세히 설명하지 않고 오라클 윈도우 함수를 사용하여이 쿼리를 간소화하고 신속하게 처리 할 수 ​​있습니다 (상관 된 하위 쿼리를 직접 저장하지 마십시오) –

+0

@ElectricLlama - 그 제안에 감사드립니다. 다행히도이 쿼리를 내 응용 프로그램에 통합 할 필요가 없습니다. 일부 이해 관계자가보고 요구에 필요한 정보를 필요로했기 때문에 일회성으로이를 실행해야했습니다. –